17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5cee86682Scalum * Common Development and Distribution License (the "License"). 6cee86682Scalum * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22eec118a1SMarcel Telka * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 23*25a1318cSMarcel Telka * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/systm.h> 277c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 287c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 297c478bd9Sstevel@tonic-gate #include <sys/atomic.h> 307c478bd9Sstevel@tonic-gate #include <sys/clconf.h> 317c478bd9Sstevel@tonic-gate #include <sys/cladm.h> 327c478bd9Sstevel@tonic-gate #include <sys/flock.h> 337c478bd9Sstevel@tonic-gate #include <nfs/export.h> 347c478bd9Sstevel@tonic-gate #include <nfs/nfs.h> 357c478bd9Sstevel@tonic-gate #include <nfs/nfs4.h> 367c478bd9Sstevel@tonic-gate #include <nfs/nfssys.h> 377c478bd9Sstevel@tonic-gate #include <nfs/lm.h> 387c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 39ed57cab9Srg137905 #include <sys/sdt.h> 40cee86682Scalum #include <sys/nvpair.h> 417c478bd9Sstevel@tonic-gate 42da6c28aaSamw extern u_longlong_t nfs4_srv_caller_id; 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate extern time_t rfs4_start_time; 451b300de9Sjwahlig extern uint_t nfs4_srv_vkey; 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate stateid4 special0 = { 487c478bd9Sstevel@tonic-gate 0, 497c478bd9Sstevel@tonic-gate { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 507c478bd9Sstevel@tonic-gate }; 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate stateid4 special1 = { 537c478bd9Sstevel@tonic-gate 0xffffffff, 547c478bd9Sstevel@tonic-gate { 557c478bd9Sstevel@tonic-gate (char)0xff, (char)0xff, (char)0xff, (char)0xff, 567c478bd9Sstevel@tonic-gate (char)0xff, (char)0xff, (char)0xff, (char)0xff, 577c478bd9Sstevel@tonic-gate (char)0xff, (char)0xff, (char)0xff, (char)0xff 587c478bd9Sstevel@tonic-gate } 597c478bd9Sstevel@tonic-gate }; 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #define ISSPECIAL(id) (stateid4_cmp(id, &special0) || \ 637c478bd9Sstevel@tonic-gate stateid4_cmp(id, &special1)) 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* For embedding the cluster nodeid into our clientid */ 667c478bd9Sstevel@tonic-gate #define CLUSTER_NODEID_SHIFT 24 677c478bd9Sstevel@tonic-gate #define CLUSTER_MAX_NODEID 255 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate #ifdef DEBUG 707c478bd9Sstevel@tonic-gate int rfs4_debug; 717c478bd9Sstevel@tonic-gate #endif 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate static uint32_t rfs4_database_debug = 0x00; 747c478bd9Sstevel@tonic-gate 75cee86682Scalum static void rfs4_ss_clid_write(rfs4_client_t *cp, char *leaf); 76cee86682Scalum static void rfs4_ss_clid_write_one(rfs4_client_t *cp, char *dir, char *leaf); 77cee86682Scalum static void rfs4_dss_clear_oldstate(rfs4_servinst_t *sip); 78cee86682Scalum static void rfs4_ss_chkclid_sip(rfs4_client_t *cp, rfs4_servinst_t *sip); 79cee86682Scalum 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * Couple of simple init/destroy functions for a general waiter 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate void 847c478bd9Sstevel@tonic-gate rfs4_sw_init(rfs4_state_wait_t *swp) 857c478bd9Sstevel@tonic-gate { 867c478bd9Sstevel@tonic-gate mutex_init(swp->sw_cv_lock, NULL, MUTEX_DEFAULT, NULL); 877c478bd9Sstevel@tonic-gate cv_init(swp->sw_cv, NULL, CV_DEFAULT, NULL); 887c478bd9Sstevel@tonic-gate swp->sw_active = FALSE; 897c478bd9Sstevel@tonic-gate swp->sw_wait_count = 0; 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate void 937c478bd9Sstevel@tonic-gate rfs4_sw_destroy(rfs4_state_wait_t *swp) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate mutex_destroy(swp->sw_cv_lock); 967c478bd9Sstevel@tonic-gate cv_destroy(swp->sw_cv); 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate void 1007c478bd9Sstevel@tonic-gate rfs4_sw_enter(rfs4_state_wait_t *swp) 1017c478bd9Sstevel@tonic-gate { 1027c478bd9Sstevel@tonic-gate mutex_enter(swp->sw_cv_lock); 1037c478bd9Sstevel@tonic-gate while (swp->sw_active) { 1047c478bd9Sstevel@tonic-gate swp->sw_wait_count++; 1057c478bd9Sstevel@tonic-gate cv_wait(swp->sw_cv, swp->sw_cv_lock); 1067c478bd9Sstevel@tonic-gate swp->sw_wait_count--; 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate ASSERT(swp->sw_active == FALSE); 1097c478bd9Sstevel@tonic-gate swp->sw_active = TRUE; 1107c478bd9Sstevel@tonic-gate mutex_exit(swp->sw_cv_lock); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate void 1147c478bd9Sstevel@tonic-gate rfs4_sw_exit(rfs4_state_wait_t *swp) 1157c478bd9Sstevel@tonic-gate { 1167c478bd9Sstevel@tonic-gate mutex_enter(swp->sw_cv_lock); 1177c478bd9Sstevel@tonic-gate ASSERT(swp->sw_active == TRUE); 1187c478bd9Sstevel@tonic-gate swp->sw_active = FALSE; 1197c478bd9Sstevel@tonic-gate if (swp->sw_wait_count != 0) 1207c478bd9Sstevel@tonic-gate cv_broadcast(swp->sw_cv); 1217c478bd9Sstevel@tonic-gate mutex_exit(swp->sw_cv_lock); 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * CPR callback id -- not related to v4 callbacks 1267c478bd9Sstevel@tonic-gate */ 1277c478bd9Sstevel@tonic-gate static callb_id_t cpr_id = 0; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate static void 1307c478bd9Sstevel@tonic-gate deep_lock_copy(LOCK4res *dres, LOCK4res *sres) 1317c478bd9Sstevel@tonic-gate { 1327c478bd9Sstevel@tonic-gate lock_owner4 *slo = &sres->LOCK4res_u.denied.owner; 1337c478bd9Sstevel@tonic-gate lock_owner4 *dlo = &dres->LOCK4res_u.denied.owner; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate if (sres->status == NFS4ERR_DENIED) { 1367c478bd9Sstevel@tonic-gate dlo->owner_val = kmem_alloc(slo->owner_len, KM_SLEEP); 1377c478bd9Sstevel@tonic-gate bcopy(slo->owner_val, dlo->owner_val, slo->owner_len); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate static void 1427c478bd9Sstevel@tonic-gate deep_lock_free(LOCK4res *res) 1437c478bd9Sstevel@tonic-gate { 1447c478bd9Sstevel@tonic-gate lock_owner4 *lo = &res->LOCK4res_u.denied.owner; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate if (res->status == NFS4ERR_DENIED) 1477c478bd9Sstevel@tonic-gate kmem_free(lo->owner_val, lo->owner_len); 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate static void 1517c478bd9Sstevel@tonic-gate deep_open_copy(OPEN4res *dres, OPEN4res *sres) 1527c478bd9Sstevel@tonic-gate { 1537c478bd9Sstevel@tonic-gate nfsace4 *sacep, *dacep; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate if (sres->status != NFS4_OK) { 1567c478bd9Sstevel@tonic-gate return; 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate dres->attrset = sres->attrset; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate switch (sres->delegation.delegation_type) { 1627c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_NONE: 1637c478bd9Sstevel@tonic-gate return; 1647c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_READ: 1657c478bd9Sstevel@tonic-gate sacep = &sres->delegation.open_delegation4_u.read.permissions; 1667c478bd9Sstevel@tonic-gate dacep = &dres->delegation.open_delegation4_u.read.permissions; 1677c478bd9Sstevel@tonic-gate break; 1687c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_WRITE: 1697c478bd9Sstevel@tonic-gate sacep = &sres->delegation.open_delegation4_u.write.permissions; 1707c478bd9Sstevel@tonic-gate dacep = &dres->delegation.open_delegation4_u.write.permissions; 1717c478bd9Sstevel@tonic-gate break; 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate dacep->who.utf8string_val = 1747c478bd9Sstevel@tonic-gate kmem_alloc(sacep->who.utf8string_len, KM_SLEEP); 1757c478bd9Sstevel@tonic-gate bcopy(sacep->who.utf8string_val, dacep->who.utf8string_val, 1767c478bd9Sstevel@tonic-gate sacep->who.utf8string_len); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate static void 1807c478bd9Sstevel@tonic-gate deep_open_free(OPEN4res *res) 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate nfsace4 *acep; 1837c478bd9Sstevel@tonic-gate if (res->status != NFS4_OK) 1847c478bd9Sstevel@tonic-gate return; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate switch (res->delegation.delegation_type) { 1877c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_NONE: 1887c478bd9Sstevel@tonic-gate return; 1897c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_READ: 1907c478bd9Sstevel@tonic-gate acep = &res->delegation.open_delegation4_u.read.permissions; 1917c478bd9Sstevel@tonic-gate break; 1927c478bd9Sstevel@tonic-gate case OPEN_DELEGATE_WRITE: 1937c478bd9Sstevel@tonic-gate acep = &res->delegation.open_delegation4_u.write.permissions; 1947c478bd9Sstevel@tonic-gate break; 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if (acep->who.utf8string_val) { 1987c478bd9Sstevel@tonic-gate kmem_free(acep->who.utf8string_val, acep->who.utf8string_len); 1997c478bd9Sstevel@tonic-gate acep->who.utf8string_val = NULL; 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate void 2047c478bd9Sstevel@tonic-gate rfs4_free_reply(nfs_resop4 *rp) 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate switch (rp->resop) { 2077c478bd9Sstevel@tonic-gate case OP_LOCK: 2087c478bd9Sstevel@tonic-gate deep_lock_free(&rp->nfs_resop4_u.oplock); 2097c478bd9Sstevel@tonic-gate break; 2107c478bd9Sstevel@tonic-gate case OP_OPEN: 2117c478bd9Sstevel@tonic-gate deep_open_free(&rp->nfs_resop4_u.opopen); 2127c478bd9Sstevel@tonic-gate default: 2137c478bd9Sstevel@tonic-gate break; 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate void 2187c478bd9Sstevel@tonic-gate rfs4_copy_reply(nfs_resop4 *dst, nfs_resop4 *src) 2197c478bd9Sstevel@tonic-gate { 2207c478bd9Sstevel@tonic-gate *dst = *src; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* Handle responses that need deep copy */ 2237c478bd9Sstevel@tonic-gate switch (src->resop) { 2247c478bd9Sstevel@tonic-gate case OP_LOCK: 2257c478bd9Sstevel@tonic-gate deep_lock_copy(&dst->nfs_resop4_u.oplock, 2267c478bd9Sstevel@tonic-gate &src->nfs_resop4_u.oplock); 2277c478bd9Sstevel@tonic-gate break; 2287c478bd9Sstevel@tonic-gate case OP_OPEN: 2297c478bd9Sstevel@tonic-gate deep_open_copy(&dst->nfs_resop4_u.opopen, 2307c478bd9Sstevel@tonic-gate &src->nfs_resop4_u.opopen); 2317c478bd9Sstevel@tonic-gate break; 2327c478bd9Sstevel@tonic-gate default: 2337c478bd9Sstevel@tonic-gate break; 2347c478bd9Sstevel@tonic-gate }; 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * This is the implementation of the underlying state engine. The 2397c478bd9Sstevel@tonic-gate * public interface to this engine is described by 2407c478bd9Sstevel@tonic-gate * nfs4_state.h. Callers to the engine should hold no state engine 2417c478bd9Sstevel@tonic-gate * locks when they call in to it. If the protocol needs to lock data 2427c478bd9Sstevel@tonic-gate * structures it should do so after acquiring all references to them 2437c478bd9Sstevel@tonic-gate * first and then follow the following lock order: 2447c478bd9Sstevel@tonic-gate * 2457c478bd9Sstevel@tonic-gate * client > openowner > state > lo_state > lockowner > file. 2467c478bd9Sstevel@tonic-gate * 2477c478bd9Sstevel@tonic-gate * Internally we only allow a thread to hold one hash bucket lock at a 2487c478bd9Sstevel@tonic-gate * time and the lock is higher in the lock order (must be acquired 2497c478bd9Sstevel@tonic-gate * first) than the data structure that is on that hash list. 2507c478bd9Sstevel@tonic-gate * 2517c478bd9Sstevel@tonic-gate * If a new reference was acquired by the caller, that reference needs 2527c478bd9Sstevel@tonic-gate * to be released after releasing all acquired locks with the 2537c478bd9Sstevel@tonic-gate * corresponding rfs4_*_rele routine. 2547c478bd9Sstevel@tonic-gate */ 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * This code is some what prototypical for now. Its purpose currently is to 2587c478bd9Sstevel@tonic-gate * implement the interfaces sufficiently to finish the higher protocol 2597c478bd9Sstevel@tonic-gate * elements. This will be replaced by a dynamically resizeable tables 2607c478bd9Sstevel@tonic-gate * backed by kmem_cache allocator. However synchronization is handled 2617c478bd9Sstevel@tonic-gate * correctly (I hope) and will not change by much. The mutexes for 2627c478bd9Sstevel@tonic-gate * the hash buckets that can be used to create new instances of data 2637c478bd9Sstevel@tonic-gate * structures might be good candidates to evolve into reader writer 2647c478bd9Sstevel@tonic-gate * locks. If it has to do a creation, it would be holding the 2657c478bd9Sstevel@tonic-gate * mutex across a kmem_alloc with KM_SLEEP specified. 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate #ifdef DEBUG 2697c478bd9Sstevel@tonic-gate #define TABSIZE 17 2707c478bd9Sstevel@tonic-gate #else 2717c478bd9Sstevel@tonic-gate #define TABSIZE 2047 2727c478bd9Sstevel@tonic-gate #endif 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate #define ADDRHASH(key) ((unsigned long)(key) >> 3) 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate /* Used to serialize create/destroy of rfs4_server_state database */ 2777c478bd9Sstevel@tonic-gate kmutex_t rfs4_state_lock; 2787c478bd9Sstevel@tonic-gate static rfs4_database_t *rfs4_server_state = NULL; 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* Used to serialize lookups of clientids */ 2817c478bd9Sstevel@tonic-gate static krwlock_t rfs4_findclient_lock; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * For now this "table" is exposed so that the CPR callback 2857c478bd9Sstevel@tonic-gate * function can tromp through it.. 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate rfs4_table_t *rfs4_client_tab; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_clientid_idx; 2907c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_nfsclnt_idx; 2912f172c55SRobert Thurlow static rfs4_table_t *rfs4_clntip_tab; 2922f172c55SRobert Thurlow static rfs4_index_t *rfs4_clntip_idx; 2937c478bd9Sstevel@tonic-gate static rfs4_table_t *rfs4_openowner_tab; 2947c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_openowner_idx; 2957c478bd9Sstevel@tonic-gate static rfs4_table_t *rfs4_state_tab; 2967c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_state_idx; 2977c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_state_owner_file_idx; 2987c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_state_file_idx; 2997c478bd9Sstevel@tonic-gate static rfs4_table_t *rfs4_lo_state_tab; 3007c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_lo_state_idx; 3017c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_lo_state_owner_idx; 3027c478bd9Sstevel@tonic-gate static rfs4_table_t *rfs4_lockowner_tab; 3037c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_lockowner_idx; 3047c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_lockowner_pid_idx; 3057c478bd9Sstevel@tonic-gate static rfs4_table_t *rfs4_file_tab; 3067c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_file_idx; 3077c478bd9Sstevel@tonic-gate static rfs4_table_t *rfs4_deleg_state_tab; 3087c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_deleg_idx; 3097c478bd9Sstevel@tonic-gate static rfs4_index_t *rfs4_deleg_state_idx; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate #define MAXTABSZ 1024*1024 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate /* The values below are rfs4_lease_time units */ 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate #ifdef DEBUG 3167c478bd9Sstevel@tonic-gate #define CLIENT_CACHE_TIME 1 3177c478bd9Sstevel@tonic-gate #define OPENOWNER_CACHE_TIME 1 3187c478bd9Sstevel@tonic-gate #define STATE_CACHE_TIME 1 3197c478bd9Sstevel@tonic-gate #define LO_STATE_CACHE_TIME 1 3207c478bd9Sstevel@tonic-gate #define LOCKOWNER_CACHE_TIME 1 3217c478bd9Sstevel@tonic-gate #define FILE_CACHE_TIME 3 3227c478bd9Sstevel@tonic-gate #define DELEG_STATE_CACHE_TIME 1 3237c478bd9Sstevel@tonic-gate #else 3247c478bd9Sstevel@tonic-gate #define CLIENT_CACHE_TIME 10 3257c478bd9Sstevel@tonic-gate #define OPENOWNER_CACHE_TIME 5 3267c478bd9Sstevel@tonic-gate #define STATE_CACHE_TIME 1 3277c478bd9Sstevel@tonic-gate #define LO_STATE_CACHE_TIME 1 3287c478bd9Sstevel@tonic-gate #define LOCKOWNER_CACHE_TIME 3 3297c478bd9Sstevel@tonic-gate #define FILE_CACHE_TIME 40 3307c478bd9Sstevel@tonic-gate #define DELEG_STATE_CACHE_TIME 1 3317c478bd9Sstevel@tonic-gate #endif 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate static time_t rfs4_client_cache_time = 0; 3352f172c55SRobert Thurlow static time_t rfs4_clntip_cache_time = 0; 3367c478bd9Sstevel@tonic-gate static time_t rfs4_openowner_cache_time = 0; 3377c478bd9Sstevel@tonic-gate static time_t rfs4_state_cache_time = 0; 3387c478bd9Sstevel@tonic-gate static time_t rfs4_lo_state_cache_time = 0; 3397c478bd9Sstevel@tonic-gate static time_t rfs4_lockowner_cache_time = 0; 3407c478bd9Sstevel@tonic-gate static time_t rfs4_file_cache_time = 0; 3417c478bd9Sstevel@tonic-gate static time_t rfs4_deleg_state_cache_time = 0; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate static bool_t rfs4_client_create(rfs4_entry_t, void *); 344cee86682Scalum static void rfs4_dss_remove_cpleaf(rfs4_client_t *); 345cee86682Scalum static void rfs4_dss_remove_leaf(rfs4_servinst_t *, char *, char *); 3467c478bd9Sstevel@tonic-gate static void rfs4_client_destroy(rfs4_entry_t); 3477c478bd9Sstevel@tonic-gate static bool_t rfs4_client_expiry(rfs4_entry_t); 3487c478bd9Sstevel@tonic-gate static uint32_t clientid_hash(void *); 3497c478bd9Sstevel@tonic-gate static bool_t clientid_compare(rfs4_entry_t, void *); 3507c478bd9Sstevel@tonic-gate static void *clientid_mkkey(rfs4_entry_t); 3517c478bd9Sstevel@tonic-gate static uint32_t nfsclnt_hash(void *); 3527c478bd9Sstevel@tonic-gate static bool_t nfsclnt_compare(rfs4_entry_t, void *); 3537c478bd9Sstevel@tonic-gate static void *nfsclnt_mkkey(rfs4_entry_t); 3542f172c55SRobert Thurlow static bool_t rfs4_clntip_expiry(rfs4_entry_t); 3552f172c55SRobert Thurlow static void rfs4_clntip_destroy(rfs4_entry_t); 3562f172c55SRobert Thurlow static bool_t rfs4_clntip_create(rfs4_entry_t, void *); 3572f172c55SRobert Thurlow static uint32_t clntip_hash(void *); 3582f172c55SRobert Thurlow static bool_t clntip_compare(rfs4_entry_t, void *); 3592f172c55SRobert Thurlow static void *clntip_mkkey(rfs4_entry_t); 3607c478bd9Sstevel@tonic-gate static bool_t rfs4_openowner_create(rfs4_entry_t, void *); 3617c478bd9Sstevel@tonic-gate static void rfs4_openowner_destroy(rfs4_entry_t); 3627c478bd9Sstevel@tonic-gate static bool_t rfs4_openowner_expiry(rfs4_entry_t); 3637c478bd9Sstevel@tonic-gate static uint32_t openowner_hash(void *); 3647c478bd9Sstevel@tonic-gate static bool_t openowner_compare(rfs4_entry_t, void *); 3657c478bd9Sstevel@tonic-gate static void *openowner_mkkey(rfs4_entry_t); 3667c478bd9Sstevel@tonic-gate static bool_t rfs4_state_create(rfs4_entry_t, void *); 3677c478bd9Sstevel@tonic-gate static void rfs4_state_destroy(rfs4_entry_t); 3687c478bd9Sstevel@tonic-gate static bool_t rfs4_state_expiry(rfs4_entry_t); 3697c478bd9Sstevel@tonic-gate static uint32_t state_hash(void *); 3707c478bd9Sstevel@tonic-gate static bool_t state_compare(rfs4_entry_t, void *); 3717c478bd9Sstevel@tonic-gate static void *state_mkkey(rfs4_entry_t); 3727c478bd9Sstevel@tonic-gate static uint32_t state_owner_file_hash(void *); 3737c478bd9Sstevel@tonic-gate static bool_t state_owner_file_compare(rfs4_entry_t, void *); 3747c478bd9Sstevel@tonic-gate static void *state_owner_file_mkkey(rfs4_entry_t); 3757c478bd9Sstevel@tonic-gate static uint32_t state_file_hash(void *); 3767c478bd9Sstevel@tonic-gate static bool_t state_file_compare(rfs4_entry_t, void *); 3777c478bd9Sstevel@tonic-gate static void *state_file_mkkey(rfs4_entry_t); 3787c478bd9Sstevel@tonic-gate static bool_t rfs4_lo_state_create(rfs4_entry_t, void *); 3797c478bd9Sstevel@tonic-gate static void rfs4_lo_state_destroy(rfs4_entry_t); 3807c478bd9Sstevel@tonic-gate static bool_t rfs4_lo_state_expiry(rfs4_entry_t); 3817c478bd9Sstevel@tonic-gate static uint32_t lo_state_hash(void *); 3827c478bd9Sstevel@tonic-gate static bool_t lo_state_compare(rfs4_entry_t, void *); 3837c478bd9Sstevel@tonic-gate static void *lo_state_mkkey(rfs4_entry_t); 3847c478bd9Sstevel@tonic-gate static uint32_t lo_state_lo_hash(void *); 3857c478bd9Sstevel@tonic-gate static bool_t lo_state_lo_compare(rfs4_entry_t, void *); 3867c478bd9Sstevel@tonic-gate static void *lo_state_lo_mkkey(rfs4_entry_t); 3877c478bd9Sstevel@tonic-gate static bool_t rfs4_lockowner_create(rfs4_entry_t, void *); 3887c478bd9Sstevel@tonic-gate static void rfs4_lockowner_destroy(rfs4_entry_t); 3897c478bd9Sstevel@tonic-gate static bool_t rfs4_lockowner_expiry(rfs4_entry_t); 3907c478bd9Sstevel@tonic-gate static uint32_t lockowner_hash(void *); 3917c478bd9Sstevel@tonic-gate static bool_t lockowner_compare(rfs4_entry_t, void *); 3927c478bd9Sstevel@tonic-gate static void *lockowner_mkkey(rfs4_entry_t); 3937c478bd9Sstevel@tonic-gate static uint32_t pid_hash(void *); 3947c478bd9Sstevel@tonic-gate static bool_t pid_compare(rfs4_entry_t, void *); 3957c478bd9Sstevel@tonic-gate static void *pid_mkkey(rfs4_entry_t); 3967c478bd9Sstevel@tonic-gate static bool_t rfs4_file_create(rfs4_entry_t, void *); 3977c478bd9Sstevel@tonic-gate static void rfs4_file_destroy(rfs4_entry_t); 3987c478bd9Sstevel@tonic-gate static uint32_t file_hash(void *); 3997c478bd9Sstevel@tonic-gate static bool_t file_compare(rfs4_entry_t, void *); 4007c478bd9Sstevel@tonic-gate static void *file_mkkey(rfs4_entry_t); 4017c478bd9Sstevel@tonic-gate static bool_t rfs4_deleg_state_create(rfs4_entry_t, void *); 4027c478bd9Sstevel@tonic-gate static void rfs4_deleg_state_destroy(rfs4_entry_t); 4037c478bd9Sstevel@tonic-gate static bool_t rfs4_deleg_state_expiry(rfs4_entry_t); 4047c478bd9Sstevel@tonic-gate static uint32_t deleg_hash(void *); 4057c478bd9Sstevel@tonic-gate static bool_t deleg_compare(rfs4_entry_t, void *); 4067c478bd9Sstevel@tonic-gate static void *deleg_mkkey(rfs4_entry_t); 4077c478bd9Sstevel@tonic-gate static uint32_t deleg_state_hash(void *); 4087c478bd9Sstevel@tonic-gate static bool_t deleg_state_compare(rfs4_entry_t, void *); 4097c478bd9Sstevel@tonic-gate static void *deleg_state_mkkey(rfs4_entry_t); 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate static void rfs4_state_rele_nounlock(rfs4_state_t *); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate static int rfs4_ss_enabled = 0; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate extern void (*rfs4_client_clrst)(struct nfs4clrst_args *); 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate void 4187c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(rfs4_ss_pn_t *ss_pn) 4197c478bd9Sstevel@tonic-gate { 4207c478bd9Sstevel@tonic-gate kmem_free(ss_pn, sizeof (rfs4_ss_pn_t)); 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate static rfs4_ss_pn_t * 4247c478bd9Sstevel@tonic-gate rfs4_ss_pnalloc(char *dir, char *leaf) 4257c478bd9Sstevel@tonic-gate { 4267c478bd9Sstevel@tonic-gate rfs4_ss_pn_t *ss_pn; 4277c478bd9Sstevel@tonic-gate int dir_len, leaf_len; 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate /* 4307c478bd9Sstevel@tonic-gate * validate we have a resonable path 4317c478bd9Sstevel@tonic-gate * (account for the '/' and trailing null) 4327c478bd9Sstevel@tonic-gate */ 4337c478bd9Sstevel@tonic-gate if ((dir_len = strlen(dir)) > MAXPATHLEN || 4347c478bd9Sstevel@tonic-gate (leaf_len = strlen(leaf)) > MAXNAMELEN || 4357c478bd9Sstevel@tonic-gate (dir_len + leaf_len + 2) > MAXPATHLEN) { 4367c478bd9Sstevel@tonic-gate return (NULL); 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate ss_pn = kmem_alloc(sizeof (rfs4_ss_pn_t), KM_SLEEP); 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate (void) snprintf(ss_pn->pn, MAXPATHLEN, "%s/%s", dir, leaf); 4427c478bd9Sstevel@tonic-gate /* Handy pointer to just the leaf name */ 4437c478bd9Sstevel@tonic-gate ss_pn->leaf = ss_pn->pn + dir_len + 1; 4447c478bd9Sstevel@tonic-gate return (ss_pn); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* 4497c478bd9Sstevel@tonic-gate * Move the "leaf" filename from "sdir" directory 4507c478bd9Sstevel@tonic-gate * to the "ddir" directory. Return the pathname of 4517c478bd9Sstevel@tonic-gate * the destination unless the rename fails in which 4527c478bd9Sstevel@tonic-gate * case we need to return the source pathname. 4537c478bd9Sstevel@tonic-gate */ 4547c478bd9Sstevel@tonic-gate static rfs4_ss_pn_t * 4557c478bd9Sstevel@tonic-gate rfs4_ss_movestate(char *sdir, char *ddir, char *leaf) 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate rfs4_ss_pn_t *src, *dst; 4587c478bd9Sstevel@tonic-gate 459cee86682Scalum if ((src = rfs4_ss_pnalloc(sdir, leaf)) == NULL) 4607c478bd9Sstevel@tonic-gate return (NULL); 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate if ((dst = rfs4_ss_pnalloc(ddir, leaf)) == NULL) { 4637c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(src); 4647c478bd9Sstevel@tonic-gate return (NULL); 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate /* 4687c478bd9Sstevel@tonic-gate * If the rename fails we shall return the src 4697c478bd9Sstevel@tonic-gate * pathname and free the dst. Otherwise we need 4707c478bd9Sstevel@tonic-gate * to free the src and return the dst pathanme. 4717c478bd9Sstevel@tonic-gate */ 4727c478bd9Sstevel@tonic-gate if (vn_rename(src->pn, dst->pn, UIO_SYSSPACE)) { 4737c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(dst); 4747c478bd9Sstevel@tonic-gate return (src); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(src); 4777c478bd9Sstevel@tonic-gate return (dst); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate static rfs4_oldstate_t * 4827c478bd9Sstevel@tonic-gate rfs4_ss_getstate(vnode_t *dvp, rfs4_ss_pn_t *ss_pn) 4837c478bd9Sstevel@tonic-gate { 4847c478bd9Sstevel@tonic-gate struct uio uio; 4857c478bd9Sstevel@tonic-gate struct iovec iov[3]; 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate rfs4_oldstate_t *cl_ss = NULL; 4887c478bd9Sstevel@tonic-gate vnode_t *vp; 4897c478bd9Sstevel@tonic-gate vattr_t va; 4907c478bd9Sstevel@tonic-gate uint_t id_len; 4917c478bd9Sstevel@tonic-gate int err, kill_file, file_vers; 4927c478bd9Sstevel@tonic-gate 493cee86682Scalum if (ss_pn == NULL) 4947c478bd9Sstevel@tonic-gate return (NULL); 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * open the state file. 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate if (vn_open(ss_pn->pn, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0) != 0) { 5007c478bd9Sstevel@tonic-gate return (NULL); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate if (vp->v_type != VREG) { 504da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL); 5057c478bd9Sstevel@tonic-gate VN_RELE(vp); 5067c478bd9Sstevel@tonic-gate return (NULL); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 509da6c28aaSamw err = VOP_ACCESS(vp, VREAD, 0, CRED(), NULL); 5107c478bd9Sstevel@tonic-gate if (err) { 5117c478bd9Sstevel@tonic-gate /* 5127c478bd9Sstevel@tonic-gate * We don't have read access? better get the heck out. 5137c478bd9Sstevel@tonic-gate */ 514da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL); 5157c478bd9Sstevel@tonic-gate VN_RELE(vp); 5167c478bd9Sstevel@tonic-gate return (NULL); 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); 5207c478bd9Sstevel@tonic-gate /* 5217c478bd9Sstevel@tonic-gate * get the file size to do some basic validation 5227c478bd9Sstevel@tonic-gate */ 5237c478bd9Sstevel@tonic-gate va.va_mask = AT_SIZE; 524da6c28aaSamw err = VOP_GETATTR(vp, &va, 0, CRED(), NULL); 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate kill_file = (va.va_size == 0 || va.va_size < 5277c478bd9Sstevel@tonic-gate (NFS4_VERIFIER_SIZE + sizeof (uint_t)+1)); 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate if (err || kill_file) { 5307c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 531da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL); 5327c478bd9Sstevel@tonic-gate VN_RELE(vp); 5337c478bd9Sstevel@tonic-gate if (kill_file) { 534da6c28aaSamw (void) VOP_REMOVE(dvp, ss_pn->leaf, CRED(), NULL, 0); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate return (NULL); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate cl_ss = kmem_alloc(sizeof (rfs4_oldstate_t), KM_SLEEP); 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate /* 5427c478bd9Sstevel@tonic-gate * build iovecs to read in the file_version, verifier and id_len 5437c478bd9Sstevel@tonic-gate */ 5447c478bd9Sstevel@tonic-gate iov[0].iov_base = (caddr_t)&file_vers; 5457c478bd9Sstevel@tonic-gate iov[0].iov_len = sizeof (int); 546cee86682Scalum iov[1].iov_base = (caddr_t)&cl_ss->cl_id4.verifier; 5477c478bd9Sstevel@tonic-gate iov[1].iov_len = NFS4_VERIFIER_SIZE; 5487c478bd9Sstevel@tonic-gate iov[2].iov_base = (caddr_t)&id_len; 5497c478bd9Sstevel@tonic-gate iov[2].iov_len = sizeof (uint_t); 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate uio.uio_iov = iov; 5527c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 3; 5537c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE; 5547c478bd9Sstevel@tonic-gate uio.uio_loffset = 0; 5557c478bd9Sstevel@tonic-gate uio.uio_resid = sizeof (int) + NFS4_VERIFIER_SIZE + sizeof (uint_t); 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate if (err = VOP_READ(vp, &uio, FREAD, CRED(), NULL)) { 5587c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 559da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL); 5607c478bd9Sstevel@tonic-gate VN_RELE(vp); 5617c478bd9Sstevel@tonic-gate kmem_free(cl_ss, sizeof (rfs4_oldstate_t)); 5627c478bd9Sstevel@tonic-gate return (NULL); 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* 5667c478bd9Sstevel@tonic-gate * if the file_version doesn't match or if the 5677c478bd9Sstevel@tonic-gate * id_len is zero or the combination of the verifier, 5687c478bd9Sstevel@tonic-gate * id_len and id_val is bigger than the file we have 5697c478bd9Sstevel@tonic-gate * a problem. If so ditch the file. 5707c478bd9Sstevel@tonic-gate */ 5717c478bd9Sstevel@tonic-gate kill_file = (file_vers != NFS4_SS_VERSION || id_len == 0 || 5727c478bd9Sstevel@tonic-gate (id_len + NFS4_VERIFIER_SIZE + sizeof (uint_t)) > va.va_size); 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate if (err || kill_file) { 5757c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 576da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL); 5777c478bd9Sstevel@tonic-gate VN_RELE(vp); 5787c478bd9Sstevel@tonic-gate kmem_free(cl_ss, sizeof (rfs4_oldstate_t)); 5797c478bd9Sstevel@tonic-gate if (kill_file) { 580da6c28aaSamw (void) VOP_REMOVE(dvp, ss_pn->leaf, CRED(), NULL, 0); 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate return (NULL); 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate /* 5867c478bd9Sstevel@tonic-gate * now get the client id value 5877c478bd9Sstevel@tonic-gate */ 5887c478bd9Sstevel@tonic-gate cl_ss->cl_id4.id_val = kmem_alloc(id_len, KM_SLEEP); 5897c478bd9Sstevel@tonic-gate iov[0].iov_base = cl_ss->cl_id4.id_val; 5907c478bd9Sstevel@tonic-gate iov[0].iov_len = id_len; 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate uio.uio_iov = iov; 5937c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 1; 5947c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE; 5957c478bd9Sstevel@tonic-gate uio.uio_resid = cl_ss->cl_id4.id_len = id_len; 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate if (err = VOP_READ(vp, &uio, FREAD, CRED(), NULL)) { 5987c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 599da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL); 6007c478bd9Sstevel@tonic-gate VN_RELE(vp); 6017c478bd9Sstevel@tonic-gate kmem_free(cl_ss->cl_id4.id_val, id_len); 6027c478bd9Sstevel@tonic-gate kmem_free(cl_ss, sizeof (rfs4_oldstate_t)); 6037c478bd9Sstevel@tonic-gate return (NULL); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 607da6c28aaSamw (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL); 6087c478bd9Sstevel@tonic-gate VN_RELE(vp); 6097c478bd9Sstevel@tonic-gate return (cl_ss); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate #ifdef nextdp 6137c478bd9Sstevel@tonic-gate #undef nextdp 6147c478bd9Sstevel@tonic-gate #endif 6157c478bd9Sstevel@tonic-gate #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate /* 618cee86682Scalum * Add entries from statedir to supplied oldstate list. 619cee86682Scalum * Optionally, move all entries from statedir -> destdir. 6207c478bd9Sstevel@tonic-gate */ 6217c478bd9Sstevel@tonic-gate void 622cee86682Scalum rfs4_ss_oldstate(rfs4_oldstate_t *oldstate, char *statedir, char *destdir) 6237c478bd9Sstevel@tonic-gate { 6247c478bd9Sstevel@tonic-gate rfs4_ss_pn_t *ss_pn; 6257c478bd9Sstevel@tonic-gate rfs4_oldstate_t *cl_ss = NULL; 6267c478bd9Sstevel@tonic-gate char *dirt = NULL; 6277c478bd9Sstevel@tonic-gate int err, dir_eof = 0, size = 0; 6287c478bd9Sstevel@tonic-gate vnode_t *dvp; 6297c478bd9Sstevel@tonic-gate struct iovec iov; 6307c478bd9Sstevel@tonic-gate struct uio uio; 6317c478bd9Sstevel@tonic-gate struct dirent64 *dep; 6327c478bd9Sstevel@tonic-gate offset_t dirchunk_offset = 0; 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate /* 6357c478bd9Sstevel@tonic-gate * open the state directory 6367c478bd9Sstevel@tonic-gate */ 637cee86682Scalum if (vn_open(statedir, UIO_SYSSPACE, FREAD, 0, &dvp, 0, 0)) 6387c478bd9Sstevel@tonic-gate return; 6397c478bd9Sstevel@tonic-gate 640da6c28aaSamw if (dvp->v_type != VDIR || VOP_ACCESS(dvp, VREAD, 0, CRED(), NULL)) 6417c478bd9Sstevel@tonic-gate goto out; 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate dirt = kmem_alloc(RFS4_SS_DIRSIZE, KM_SLEEP); 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate /* 6467c478bd9Sstevel@tonic-gate * Get and process the directory entries 6477c478bd9Sstevel@tonic-gate */ 6487c478bd9Sstevel@tonic-gate while (!dir_eof) { 6497c478bd9Sstevel@tonic-gate (void) VOP_RWLOCK(dvp, V_WRITELOCK_FALSE, NULL); 6507c478bd9Sstevel@tonic-gate iov.iov_base = dirt; 6517c478bd9Sstevel@tonic-gate iov.iov_len = RFS4_SS_DIRSIZE; 6527c478bd9Sstevel@tonic-gate uio.uio_iov = &iov; 6537c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 1; 6547c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE; 6557c478bd9Sstevel@tonic-gate uio.uio_loffset = dirchunk_offset; 6567c478bd9Sstevel@tonic-gate uio.uio_resid = RFS4_SS_DIRSIZE; 6577c478bd9Sstevel@tonic-gate 658da6c28aaSamw err = VOP_READDIR(dvp, &uio, CRED(), &dir_eof, NULL, 0); 6597c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(dvp, V_WRITELOCK_FALSE, NULL); 660cee86682Scalum if (err) 6617c478bd9Sstevel@tonic-gate goto out; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate size = RFS4_SS_DIRSIZE - uio.uio_resid; 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* 6667c478bd9Sstevel@tonic-gate * Process all the directory entries in this 6677c478bd9Sstevel@tonic-gate * readdir chunk 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate for (dep = (struct dirent64 *)dirt; size > 0; 6707c478bd9Sstevel@tonic-gate dep = nextdp(dep)) { 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate size -= dep->d_reclen; 6737c478bd9Sstevel@tonic-gate dirchunk_offset = dep->d_off; 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate /* 6767c478bd9Sstevel@tonic-gate * Skip '.' and '..' 6777c478bd9Sstevel@tonic-gate */ 678cee86682Scalum if (NFS_IS_DOTNAME(dep->d_name)) 6797c478bd9Sstevel@tonic-gate continue; 6807c478bd9Sstevel@tonic-gate 681cee86682Scalum ss_pn = rfs4_ss_pnalloc(statedir, dep->d_name); 682cee86682Scalum if (ss_pn == NULL) 6837c478bd9Sstevel@tonic-gate continue; 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate if (cl_ss = rfs4_ss_getstate(dvp, ss_pn)) { 686cee86682Scalum if (destdir != NULL) { 6877c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(ss_pn); 6887c478bd9Sstevel@tonic-gate cl_ss->ss_pn = rfs4_ss_movestate( 689cee86682Scalum statedir, destdir, dep->d_name); 6907c478bd9Sstevel@tonic-gate } else { 6917c478bd9Sstevel@tonic-gate cl_ss->ss_pn = ss_pn; 6927c478bd9Sstevel@tonic-gate } 693cee86682Scalum insque(cl_ss, oldstate); 6947c478bd9Sstevel@tonic-gate } else { 6957c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(ss_pn); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate 700cee86682Scalum out: 701da6c28aaSamw (void) VOP_CLOSE(dvp, FREAD, 1, (offset_t)0, CRED(), NULL); 7027c478bd9Sstevel@tonic-gate VN_RELE(dvp); 7037c478bd9Sstevel@tonic-gate if (dirt) 7047c478bd9Sstevel@tonic-gate kmem_free((caddr_t)dirt, RFS4_SS_DIRSIZE); 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate static void 7087c478bd9Sstevel@tonic-gate rfs4_ss_init(void) 7097c478bd9Sstevel@tonic-gate { 710cee86682Scalum int npaths = 1; 711cee86682Scalum char *default_dss_path = NFS4_DSS_VAR_DIR; 7127c478bd9Sstevel@tonic-gate 713cee86682Scalum /* read the default stable storage state */ 714cee86682Scalum rfs4_dss_readstate(npaths, &default_dss_path); 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate rfs4_ss_enabled = 1; 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate static void 7207c478bd9Sstevel@tonic-gate rfs4_ss_fini(void) 7217c478bd9Sstevel@tonic-gate { 722cee86682Scalum rfs4_servinst_t *sip; 7237c478bd9Sstevel@tonic-gate 724cee86682Scalum mutex_enter(&rfs4_servinst_lock); 725cee86682Scalum sip = rfs4_cur_servinst; 726cee86682Scalum while (sip != NULL) { 727cee86682Scalum rfs4_dss_clear_oldstate(sip); 728cee86682Scalum sip = sip->next; 729cee86682Scalum } 730cee86682Scalum mutex_exit(&rfs4_servinst_lock); 731cee86682Scalum } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate /* 734cee86682Scalum * Remove all oldstate files referenced by this servinst. 7357c478bd9Sstevel@tonic-gate */ 736cee86682Scalum static void 737cee86682Scalum rfs4_dss_clear_oldstate(rfs4_servinst_t *sip) 738cee86682Scalum { 739cee86682Scalum rfs4_oldstate_t *os_head, *osp; 740cee86682Scalum 741cee86682Scalum rw_enter(&sip->oldstate_lock, RW_WRITER); 742cee86682Scalum os_head = sip->oldstate; 743cee86682Scalum 744eec118a1SMarcel Telka if (os_head == NULL) { 745eec118a1SMarcel Telka rw_exit(&sip->oldstate_lock); 7467c478bd9Sstevel@tonic-gate return; 747eec118a1SMarcel Telka } 748cee86682Scalum 749cee86682Scalum /* skip dummy entry */ 750cee86682Scalum osp = os_head->next; 751cee86682Scalum while (osp != os_head) { 752cee86682Scalum char *leaf = osp->ss_pn->leaf; 753cee86682Scalum rfs4_oldstate_t *os_next; 754cee86682Scalum 755cee86682Scalum rfs4_dss_remove_leaf(sip, NFS4_DSS_OLDSTATE_LEAF, leaf); 756cee86682Scalum 757cee86682Scalum if (osp->cl_id4.id_val) 758cee86682Scalum kmem_free(osp->cl_id4.id_val, osp->cl_id4.id_len); 759eec118a1SMarcel Telka rfs4_ss_pnfree(osp->ss_pn); 760cee86682Scalum 761cee86682Scalum os_next = osp->next; 762cee86682Scalum remque(osp); 763cee86682Scalum kmem_free(osp, sizeof (rfs4_oldstate_t)); 764cee86682Scalum osp = os_next; 765cee86682Scalum } 766cee86682Scalum 767cee86682Scalum rw_exit(&sip->oldstate_lock); 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate /* 771cee86682Scalum * Form the state and oldstate paths, and read in the stable storage files. 7727c478bd9Sstevel@tonic-gate */ 773cee86682Scalum void 774cee86682Scalum rfs4_dss_readstate(int npaths, char **paths) 775cee86682Scalum { 776cee86682Scalum int i; 777cee86682Scalum char *state, *oldstate; 7787c478bd9Sstevel@tonic-gate 779cee86682Scalum state = kmem_alloc(MAXPATHLEN, KM_SLEEP); 780cee86682Scalum oldstate = kmem_alloc(MAXPATHLEN, KM_SLEEP); 781cee86682Scalum 782cee86682Scalum for (i = 0; i < npaths; i++) { 783cee86682Scalum char *path = paths[i]; 784cee86682Scalum 785cee86682Scalum (void) sprintf(state, "%s/%s", path, NFS4_DSS_STATE_LEAF); 786cee86682Scalum (void) sprintf(oldstate, "%s/%s", path, NFS4_DSS_OLDSTATE_LEAF); 787cee86682Scalum 788cee86682Scalum /* 789cee86682Scalum * Populate the current server instance's oldstate list. 790cee86682Scalum * 791cee86682Scalum * 1. Read stable storage data from old state directory, 792cee86682Scalum * leaving its contents alone. 793cee86682Scalum * 794cee86682Scalum * 2. Read stable storage data from state directory, 795cee86682Scalum * and move the latter's contents to old state 796cee86682Scalum * directory. 797cee86682Scalum */ 798cee86682Scalum rfs4_ss_oldstate(rfs4_cur_servinst->oldstate, oldstate, NULL); 799cee86682Scalum rfs4_ss_oldstate(rfs4_cur_servinst->oldstate, state, oldstate); 8007c478bd9Sstevel@tonic-gate } 801cee86682Scalum 802cee86682Scalum kmem_free(state, MAXPATHLEN); 803cee86682Scalum kmem_free(oldstate, MAXPATHLEN); 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate /* 8087c478bd9Sstevel@tonic-gate * Check if we are still in grace and if the client can be 8097c478bd9Sstevel@tonic-gate * granted permission to perform reclaims. 8107c478bd9Sstevel@tonic-gate */ 8117c478bd9Sstevel@tonic-gate void 8127c478bd9Sstevel@tonic-gate rfs4_ss_chkclid(rfs4_client_t *cp) 8137c478bd9Sstevel@tonic-gate { 814cee86682Scalum rfs4_servinst_t *sip; 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate /* 817cee86682Scalum * It should be sufficient to check the oldstate data for just 818cee86682Scalum * this client's instance. However, since our per-instance 819cee86682Scalum * client grouping is solely temporal, HA-NFSv4 RG failover 820cee86682Scalum * might result in clients of the same RG being partitioned into 821cee86682Scalum * separate instances. 822cee86682Scalum * 823cee86682Scalum * Until the client grouping is improved, we must check the 824cee86682Scalum * oldstate data for all instances with an active grace period. 825cee86682Scalum * 826cee86682Scalum * This also serves as the mechanism to remove stale oldstate data. 827cee86682Scalum * The first time we check an instance after its grace period has 828cee86682Scalum * expired, the oldstate data should be cleared. 829cee86682Scalum * 830cee86682Scalum * Start at the current instance, and walk the list backwards 831cee86682Scalum * to the first. 8327c478bd9Sstevel@tonic-gate */ 833cee86682Scalum mutex_enter(&rfs4_servinst_lock); 834cee86682Scalum for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev) { 835cee86682Scalum rfs4_ss_chkclid_sip(cp, sip); 836cee86682Scalum 837cee86682Scalum /* if the above check found this client, we're done */ 838d216dff5SRobert Mastors if (cp->rc_can_reclaim) 839cee86682Scalum break; 840cee86682Scalum } 841cee86682Scalum mutex_exit(&rfs4_servinst_lock); 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate 844cee86682Scalum static void 845cee86682Scalum rfs4_ss_chkclid_sip(rfs4_client_t *cp, rfs4_servinst_t *sip) 846cee86682Scalum { 847cee86682Scalum rfs4_oldstate_t *osp, *os_head; 848cee86682Scalum 849cee86682Scalum /* short circuit everything if this server instance has no oldstate */ 850cee86682Scalum rw_enter(&sip->oldstate_lock, RW_READER); 851cee86682Scalum os_head = sip->oldstate; 852cee86682Scalum rw_exit(&sip->oldstate_lock); 853cee86682Scalum if (os_head == NULL) 8547c478bd9Sstevel@tonic-gate return; 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate /* 857cee86682Scalum * If this server instance is no longer in a grace period then 858cee86682Scalum * the client won't be able to reclaim. No further need for this 859cee86682Scalum * instance's oldstate data, so it can be cleared. 8607c478bd9Sstevel@tonic-gate */ 861cee86682Scalum if (!rfs4_servinst_in_grace(sip)) 862cee86682Scalum return; 863cee86682Scalum 864cee86682Scalum /* this instance is still in grace; search for the clientid */ 865cee86682Scalum 866cee86682Scalum rw_enter(&sip->oldstate_lock, RW_READER); 867cee86682Scalum 868cee86682Scalum os_head = sip->oldstate; 869cee86682Scalum /* skip dummy entry */ 8707c478bd9Sstevel@tonic-gate osp = os_head->next; 8717c478bd9Sstevel@tonic-gate while (osp != os_head) { 872d216dff5SRobert Mastors if (osp->cl_id4.id_len == cp->rc_nfs_client.id_len) { 873d216dff5SRobert Mastors if (bcmp(osp->cl_id4.id_val, cp->rc_nfs_client.id_val, 8747c478bd9Sstevel@tonic-gate osp->cl_id4.id_len) == 0) { 875d216dff5SRobert Mastors cp->rc_can_reclaim = 1; 8767c478bd9Sstevel@tonic-gate break; 8777c478bd9Sstevel@tonic-gate } 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate osp = osp->next; 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate 882cee86682Scalum rw_exit(&sip->oldstate_lock); 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate /* 886cee86682Scalum * Place client information into stable storage: 1/3. 887cee86682Scalum * First, generate the leaf filename, from the client's IP address and 888cee86682Scalum * the server-generated short-hand clientid. 8897c478bd9Sstevel@tonic-gate */ 8907c478bd9Sstevel@tonic-gate void 8912f172c55SRobert Thurlow rfs4_ss_clid(rfs4_client_t *cp) 8927c478bd9Sstevel@tonic-gate { 8937c478bd9Sstevel@tonic-gate const char *kinet_ntop6(uchar_t *, char *, size_t); 8947c478bd9Sstevel@tonic-gate char leaf[MAXNAMELEN], buf[INET6_ADDRSTRLEN]; 8957c478bd9Sstevel@tonic-gate struct sockaddr *ca; 8967c478bd9Sstevel@tonic-gate uchar_t *b; 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate if (rfs4_ss_enabled == 0) { 8997c478bd9Sstevel@tonic-gate return; 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate buf[0] = 0; 9037c478bd9Sstevel@tonic-gate 9042f172c55SRobert Thurlow ca = (struct sockaddr *)&cp->rc_addr; 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate /* 9077c478bd9Sstevel@tonic-gate * Convert the caller's IP address to a dotted string 9087c478bd9Sstevel@tonic-gate */ 9097c478bd9Sstevel@tonic-gate if (ca->sa_family == AF_INET) { 9107c478bd9Sstevel@tonic-gate b = (uchar_t *)&((struct sockaddr_in *)ca)->sin_addr; 9117c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%03d.%03d.%03d.%03d", b[0] & 0xFF, 9127c478bd9Sstevel@tonic-gate b[1] & 0xFF, b[2] & 0xFF, b[3] & 0xFF); 9137c478bd9Sstevel@tonic-gate } else if (ca->sa_family == AF_INET6) { 9147c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)ca; 9177c478bd9Sstevel@tonic-gate (void) kinet_ntop6((uchar_t *)&sin6->sin6_addr, 9187c478bd9Sstevel@tonic-gate buf, INET6_ADDRSTRLEN); 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate (void) snprintf(leaf, MAXNAMELEN, "%s-%llx", buf, 922d216dff5SRobert Mastors (longlong_t)cp->rc_clientid); 923cee86682Scalum rfs4_ss_clid_write(cp, leaf); 9247c478bd9Sstevel@tonic-gate } 9257c478bd9Sstevel@tonic-gate 926cee86682Scalum /* 927cee86682Scalum * Place client information into stable storage: 2/3. 928cee86682Scalum * DSS: distributed stable storage: the file may need to be written to 929cee86682Scalum * multiple directories. 930cee86682Scalum */ 931cee86682Scalum static void 932cee86682Scalum rfs4_ss_clid_write(rfs4_client_t *cp, char *leaf) 933cee86682Scalum { 934cee86682Scalum rfs4_servinst_t *sip; 935cee86682Scalum 936cee86682Scalum /* 937cee86682Scalum * It should be sufficient to write the leaf file to (all) DSS paths 938cee86682Scalum * associated with just this client's instance. However, since our 939cee86682Scalum * per-instance client grouping is solely temporal, HA-NFSv4 RG 940cee86682Scalum * failover might result in us losing DSS data. 941cee86682Scalum * 942cee86682Scalum * Until the client grouping is improved, we must write the DSS data 943cee86682Scalum * to all instances' paths. Start at the current instance, and 944cee86682Scalum * walk the list backwards to the first. 945cee86682Scalum */ 946cee86682Scalum mutex_enter(&rfs4_servinst_lock); 947cee86682Scalum for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev) { 948cee86682Scalum int i, npaths = sip->dss_npaths; 949cee86682Scalum 950cee86682Scalum /* write the leaf file to all DSS paths */ 951cee86682Scalum for (i = 0; i < npaths; i++) { 952cee86682Scalum rfs4_dss_path_t *dss_path = sip->dss_paths[i]; 953cee86682Scalum 954cee86682Scalum /* HA-NFSv4 path might have been failed-away from us */ 955cee86682Scalum if (dss_path == NULL) 956cee86682Scalum continue; 957cee86682Scalum 958cee86682Scalum rfs4_ss_clid_write_one(cp, dss_path->path, leaf); 959cee86682Scalum } 960cee86682Scalum } 961cee86682Scalum mutex_exit(&rfs4_servinst_lock); 962cee86682Scalum } 963cee86682Scalum 964cee86682Scalum /* 965cee86682Scalum * Place client information into stable storage: 3/3. 966cee86682Scalum * Write the stable storage data to the requested file. 967cee86682Scalum */ 968cee86682Scalum static void 969cee86682Scalum rfs4_ss_clid_write_one(rfs4_client_t *cp, char *dss_path, char *leaf) 970cee86682Scalum { 971cee86682Scalum int ioflag; 972cee86682Scalum int file_vers = NFS4_SS_VERSION; 97397669b90Scalum size_t dirlen; 974cee86682Scalum struct uio uio; 975cee86682Scalum struct iovec iov[4]; 976cee86682Scalum char *dir; 977cee86682Scalum rfs4_ss_pn_t *ss_pn; 978cee86682Scalum vnode_t *vp; 979d216dff5SRobert Mastors nfs_client_id4 *cl_id4 = &(cp->rc_nfs_client); 980cee86682Scalum 981cee86682Scalum /* allow 2 extra bytes for '/' & NUL */ 98297669b90Scalum dirlen = strlen(dss_path) + strlen(NFS4_DSS_STATE_LEAF) + 2; 98397669b90Scalum dir = kmem_alloc(dirlen, KM_SLEEP); 984cee86682Scalum (void) sprintf(dir, "%s/%s", dss_path, NFS4_DSS_STATE_LEAF); 985cee86682Scalum 98697669b90Scalum ss_pn = rfs4_ss_pnalloc(dir, leaf); 98797669b90Scalum /* rfs4_ss_pnalloc takes its own copy */ 98897669b90Scalum kmem_free(dir, dirlen); 98997669b90Scalum if (ss_pn == NULL) 990cee86682Scalum return; 991cee86682Scalum 9927c478bd9Sstevel@tonic-gate if (vn_open(ss_pn->pn, UIO_SYSSPACE, FCREAT|FWRITE, 0600, &vp, 9937c478bd9Sstevel@tonic-gate CRCREAT, 0)) { 9947c478bd9Sstevel@tonic-gate rfs4_ss_pnfree(ss_pn); 9957c478bd9Sstevel@tonic-gate return; 9967c478bd9Sstevel@tonic-gate } 9977c478bd9Sstevel@tonic-gate 998cee86682Scalum /* 999cee86682Scalum * We need to record leaf - i.e. the filename - so that we know 1000cee86682Scalum * what to remove, in the future. However, the dir part of cp->ss_pn 1001cee86682Scalum * should never be referenced directly, since it's potentially only 1002cee86682Scalum * one of several paths with this leaf in it. 1003cee86682Scalum */ 1004d216dff5SRobert Mastors if (cp->rc_ss_pn != NULL) { 1005d216dff5SRobert Mastors if (strcmp(cp->rc_ss_pn->leaf, leaf) == 0) { 1006cee86682Scalum /* we've already recorded *this* leaf */ 1007cee86682Scalum rfs4_ss_pnfree(ss_pn); 1008cee86682Scalum } else { 1009cee86682Scalum /* replace with this leaf */ 1010d216dff5SRobert Mastors rfs4_ss_pnfree(cp->rc_ss_pn); 1011d216dff5SRobert Mastors cp->rc_ss_pn = ss_pn; 1012cee86682Scalum } 1013cee86682Scalum } else { 1014d216dff5SRobert Mastors cp->rc_ss_pn = ss_pn; 1015cee86682Scalum } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate /* 10187c478bd9Sstevel@tonic-gate * Build a scatter list that points to the nfs_client_id4 10197c478bd9Sstevel@tonic-gate */ 10207c478bd9Sstevel@tonic-gate iov[0].iov_base = (caddr_t)&file_vers; 10217c478bd9Sstevel@tonic-gate iov[0].iov_len = sizeof (int); 1022cee86682Scalum iov[1].iov_base = (caddr_t)&(cl_id4->verifier); 10237c478bd9Sstevel@tonic-gate iov[1].iov_len = NFS4_VERIFIER_SIZE; 10247c478bd9Sstevel@tonic-gate iov[2].iov_base = (caddr_t)&(cl_id4->id_len); 10257c478bd9Sstevel@tonic-gate iov[2].iov_len = sizeof (uint_t); 10267c478bd9Sstevel@tonic-gate iov[3].iov_base = (caddr_t)cl_id4->id_val; 10277c478bd9Sstevel@tonic-gate iov[3].iov_len = cl_id4->id_len; 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate uio.uio_iov = iov; 10307c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 4; 10317c478bd9Sstevel@tonic-gate uio.uio_loffset = 0; 10327c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE; 10337c478bd9Sstevel@tonic-gate uio.uio_llimit = (rlim64_t)MAXOFFSET_T; 10347c478bd9Sstevel@tonic-gate uio.uio_resid = cl_id4->id_len + sizeof (int) + 10357c478bd9Sstevel@tonic-gate NFS4_VERIFIER_SIZE + sizeof (uint_t); 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate ioflag = uio.uio_fmode = (FWRITE|FSYNC); 10387c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_DEFAULT; 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); 10417c478bd9Sstevel@tonic-gate /* write the full client id to the file. */ 10427c478bd9Sstevel@tonic-gate (void) VOP_WRITE(vp, &uio, ioflag, CRED(), NULL); 10437c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); 10447c478bd9Sstevel@tonic-gate 1045da6c28aaSamw (void) VOP_CLOSE(vp, FWRITE, 1, (offset_t)0, CRED(), NULL); 10467c478bd9Sstevel@tonic-gate VN_RELE(vp); 10477c478bd9Sstevel@tonic-gate } 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate /* 1050cee86682Scalum * DSS: distributed stable storage. 1051cee86682Scalum * Unpack the list of paths passed by nfsd. 1052cee86682Scalum * Use nvlist_alloc(9F) to manage the data. 1053cee86682Scalum * The caller is responsible for allocating and freeing the buffer. 1054cee86682Scalum */ 1055cee86682Scalum int 1056cee86682Scalum rfs4_dss_setpaths(char *buf, size_t buflen) 1057cee86682Scalum { 1058cee86682Scalum int error; 1059cee86682Scalum 1060cee86682Scalum /* 1061cee86682Scalum * If this is a "warm start", i.e. we previously had DSS paths, 1062cee86682Scalum * preserve the old paths. 1063cee86682Scalum */ 1064cee86682Scalum if (rfs4_dss_paths != NULL) { 1065cee86682Scalum /* 1066cee86682Scalum * Before we lose the ptr, destroy the nvlist and pathnames 1067cee86682Scalum * array from the warm start before this one. 1068cee86682Scalum */ 1069cee86682Scalum nvlist_free(rfs4_dss_oldpaths); 1070cee86682Scalum rfs4_dss_oldpaths = rfs4_dss_paths; 1071cee86682Scalum } 1072cee86682Scalum 1073cee86682Scalum /* unpack the buffer into a searchable nvlist */ 1074cee86682Scalum error = nvlist_unpack(buf, buflen, &rfs4_dss_paths, KM_SLEEP); 1075cee86682Scalum if (error) 1076cee86682Scalum return (error); 1077cee86682Scalum 1078cee86682Scalum /* 1079cee86682Scalum * Search the nvlist for the pathnames nvpair (which is the only nvpair 1080cee86682Scalum * in the list, and record its location. 1081cee86682Scalum */ 1082cee86682Scalum error = nvlist_lookup_string_array(rfs4_dss_paths, NFS4_DSS_NVPAIR_NAME, 1083cee86682Scalum &rfs4_dss_newpaths, &rfs4_dss_numnewpaths); 1084cee86682Scalum return (error); 1085cee86682Scalum } 1086cee86682Scalum 1087cee86682Scalum /* 10887c478bd9Sstevel@tonic-gate * Ultimately the nfssys() call NFS4_CLR_STATE endsup here 10897c478bd9Sstevel@tonic-gate * to find and mark the client for forced expire. 10907c478bd9Sstevel@tonic-gate */ 10917c478bd9Sstevel@tonic-gate static void 10927c478bd9Sstevel@tonic-gate rfs4_client_scrub(rfs4_entry_t ent, void *arg) 10937c478bd9Sstevel@tonic-gate { 10947c478bd9Sstevel@tonic-gate rfs4_client_t *cp = (rfs4_client_t *)ent; 10957c478bd9Sstevel@tonic-gate struct nfs4clrst_args *clr = arg; 10967c478bd9Sstevel@tonic-gate struct sockaddr_in6 *ent_sin6; 10977c478bd9Sstevel@tonic-gate struct in6_addr clr_in6; 10987c478bd9Sstevel@tonic-gate struct sockaddr_in *ent_sin; 10997c478bd9Sstevel@tonic-gate struct in_addr clr_in; 11007c478bd9Sstevel@tonic-gate 1101d216dff5SRobert Mastors if (clr->addr_type != cp->rc_addr.ss_family) { 11027c478bd9Sstevel@tonic-gate return; 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate switch (clr->addr_type) { 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate case AF_INET6: 11087c478bd9Sstevel@tonic-gate /* copyin the address from user space */ 11097c478bd9Sstevel@tonic-gate if (copyin(clr->ap, &clr_in6, sizeof (clr_in6))) { 11107c478bd9Sstevel@tonic-gate break; 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate 1113d216dff5SRobert Mastors ent_sin6 = (struct sockaddr_in6 *)&cp->rc_addr; 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate /* 11167c478bd9Sstevel@tonic-gate * now compare, and if equivalent mark entry 11177c478bd9Sstevel@tonic-gate * for forced expiration 11187c478bd9Sstevel@tonic-gate */ 11197c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&ent_sin6->sin6_addr, &clr_in6)) { 1120d216dff5SRobert Mastors cp->rc_forced_expire = 1; 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate break; 11237c478bd9Sstevel@tonic-gate 11247c478bd9Sstevel@tonic-gate case AF_INET: 11257c478bd9Sstevel@tonic-gate /* copyin the address from user space */ 11267c478bd9Sstevel@tonic-gate if (copyin(clr->ap, &clr_in, sizeof (clr_in))) { 11277c478bd9Sstevel@tonic-gate break; 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate 1130d216dff5SRobert Mastors ent_sin = (struct sockaddr_in *)&cp->rc_addr; 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate /* 11337c478bd9Sstevel@tonic-gate * now compare, and if equivalent mark entry 11347c478bd9Sstevel@tonic-gate * for forced expiration 11357c478bd9Sstevel@tonic-gate */ 11367c478bd9Sstevel@tonic-gate if (ent_sin->sin_addr.s_addr == clr_in.s_addr) { 1137d216dff5SRobert Mastors cp->rc_forced_expire = 1; 11387c478bd9Sstevel@tonic-gate } 11397c478bd9Sstevel@tonic-gate break; 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate default: 11427c478bd9Sstevel@tonic-gate /* force this assert to fail */ 11437c478bd9Sstevel@tonic-gate ASSERT(clr->addr_type != clr->addr_type); 11447c478bd9Sstevel@tonic-gate } 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate /* 11487c478bd9Sstevel@tonic-gate * This is called from nfssys() in order to clear server state 11497c478bd9Sstevel@tonic-gate * for the specified client IP Address. 11507c478bd9Sstevel@tonic-gate */ 11517c478bd9Sstevel@tonic-gate void 11527c478bd9Sstevel@tonic-gate rfs4_clear_client_state(struct nfs4clrst_args *clr) 11537c478bd9Sstevel@tonic-gate { 11547c478bd9Sstevel@tonic-gate (void) rfs4_dbe_walk(rfs4_client_tab, rfs4_client_scrub, clr); 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate /* 11587c478bd9Sstevel@tonic-gate * Used to initialize the NFSv4 server's state or database. All of 11597c478bd9Sstevel@tonic-gate * the tables are created and timers are set. Only called when NFSv4 11607c478bd9Sstevel@tonic-gate * service is provided. 11617c478bd9Sstevel@tonic-gate */ 11627c478bd9Sstevel@tonic-gate void 11637c478bd9Sstevel@tonic-gate rfs4_state_init() 11647c478bd9Sstevel@tonic-gate { 11657c478bd9Sstevel@tonic-gate int start_grace; 11667c478bd9Sstevel@tonic-gate extern boolean_t rfs4_cpr_callb(void *, int); 1167cee86682Scalum char *dss_path = NFS4_DSS_VAR_DIR; 1168*25a1318cSMarcel Telka time_t start_time; 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate mutex_enter(&rfs4_state_lock); 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate /* 11737c478bd9Sstevel@tonic-gate * If the server state database has already been initialized, 11747c478bd9Sstevel@tonic-gate * skip it 11757c478bd9Sstevel@tonic-gate */ 11767c478bd9Sstevel@tonic-gate if (rfs4_server_state != NULL) { 11777c478bd9Sstevel@tonic-gate mutex_exit(&rfs4_state_lock); 11787c478bd9Sstevel@tonic-gate return; 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate rw_init(&rfs4_findclient_lock, NULL, RW_DEFAULT, NULL); 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate /* 11847c478bd9Sstevel@tonic-gate * Set the boot time. If the server 11857c478bd9Sstevel@tonic-gate * has been restarted quickly and has had the opportunity to 11867c478bd9Sstevel@tonic-gate * service clients, then the start_time needs to be bumped 11877c478bd9Sstevel@tonic-gate * regardless. A small window but it exists... 11887c478bd9Sstevel@tonic-gate */ 1189*25a1318cSMarcel Telka start_time = gethrestime_sec(); 1190*25a1318cSMarcel Telka if (rfs4_start_time < start_time) 1191*25a1318cSMarcel Telka rfs4_start_time = start_time; 11927c478bd9Sstevel@tonic-gate else 11937c478bd9Sstevel@tonic-gate rfs4_start_time++; 11947c478bd9Sstevel@tonic-gate 1195cee86682Scalum /* DSS: distributed stable storage: initialise served paths list */ 1196cee86682Scalum rfs4_dss_pathlist = NULL; 1197cee86682Scalum 11987c478bd9Sstevel@tonic-gate /* 11997c478bd9Sstevel@tonic-gate * Create the first server instance, or a new one if the server has 12007c478bd9Sstevel@tonic-gate * been restarted; see above comments on rfs4_start_time. Don't 12017c478bd9Sstevel@tonic-gate * start its grace period; that will be done later, to maximise the 12027c478bd9Sstevel@tonic-gate * clients' recovery window. 12037c478bd9Sstevel@tonic-gate */ 12047c478bd9Sstevel@tonic-gate start_grace = 0; 1205cee86682Scalum rfs4_servinst_create(start_grace, 1, &dss_path); 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate /* reset the "first NFSv4 request" status */ 12087c478bd9Sstevel@tonic-gate rfs4_seen_first_compound = 0; 12097c478bd9Sstevel@tonic-gate 12107c478bd9Sstevel@tonic-gate /* 12117c478bd9Sstevel@tonic-gate * Add a CPR callback so that we can update client 12127c478bd9Sstevel@tonic-gate * access times to extend the lease after a suspend 12137c478bd9Sstevel@tonic-gate * and resume (using the same class as rpcmod/connmgr) 12147c478bd9Sstevel@tonic-gate */ 12157c478bd9Sstevel@tonic-gate cpr_id = callb_add(rfs4_cpr_callb, 0, CB_CL_CPR_RPC, "rfs4"); 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate /* set the various cache timers for table creation */ 12187c478bd9Sstevel@tonic-gate if (rfs4_client_cache_time == 0) 12197c478bd9Sstevel@tonic-gate rfs4_client_cache_time = CLIENT_CACHE_TIME; 12207c478bd9Sstevel@tonic-gate if (rfs4_openowner_cache_time == 0) 12217c478bd9Sstevel@tonic-gate rfs4_openowner_cache_time = OPENOWNER_CACHE_TIME; 12227c478bd9Sstevel@tonic-gate if (rfs4_state_cache_time == 0) 12237c478bd9Sstevel@tonic-gate rfs4_state_cache_time = STATE_CACHE_TIME; 12247c478bd9Sstevel@tonic-gate if (rfs4_lo_state_cache_time == 0) 12257c478bd9Sstevel@tonic-gate rfs4_lo_state_cache_time = LO_STATE_CACHE_TIME; 12267c478bd9Sstevel@tonic-gate if (rfs4_lockowner_cache_time == 0) 12277c478bd9Sstevel@tonic-gate rfs4_lockowner_cache_time = LOCKOWNER_CACHE_TIME; 12287c478bd9Sstevel@tonic-gate if (rfs4_file_cache_time == 0) 12297c478bd9Sstevel@tonic-gate rfs4_file_cache_time = FILE_CACHE_TIME; 12307c478bd9Sstevel@tonic-gate if (rfs4_deleg_state_cache_time == 0) 12317c478bd9Sstevel@tonic-gate rfs4_deleg_state_cache_time = DELEG_STATE_CACHE_TIME; 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate /* Create the overall database to hold all server state */ 12347c478bd9Sstevel@tonic-gate rfs4_server_state = rfs4_database_create(rfs4_database_debug); 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate /* Now create the individual tables */ 12377c478bd9Sstevel@tonic-gate rfs4_client_cache_time *= rfs4_lease_time; 12387c478bd9Sstevel@tonic-gate rfs4_client_tab = rfs4_table_create(rfs4_server_state, 12397c478bd9Sstevel@tonic-gate "Client", 12407c478bd9Sstevel@tonic-gate rfs4_client_cache_time, 12417c478bd9Sstevel@tonic-gate 2, 12427c478bd9Sstevel@tonic-gate rfs4_client_create, 12437c478bd9Sstevel@tonic-gate rfs4_client_destroy, 12447c478bd9Sstevel@tonic-gate rfs4_client_expiry, 12457c478bd9Sstevel@tonic-gate sizeof (rfs4_client_t), 12467c478bd9Sstevel@tonic-gate TABSIZE, 12477c478bd9Sstevel@tonic-gate MAXTABSZ/8, 100); 12487c478bd9Sstevel@tonic-gate rfs4_nfsclnt_idx = rfs4_index_create(rfs4_client_tab, 12497c478bd9Sstevel@tonic-gate "nfs_client_id4", nfsclnt_hash, 12507c478bd9Sstevel@tonic-gate nfsclnt_compare, nfsclnt_mkkey, 12517c478bd9Sstevel@tonic-gate TRUE); 12527c478bd9Sstevel@tonic-gate rfs4_clientid_idx = rfs4_index_create(rfs4_client_tab, 12537c478bd9Sstevel@tonic-gate "client_id", clientid_hash, 12547c478bd9Sstevel@tonic-gate clientid_compare, clientid_mkkey, 12557c478bd9Sstevel@tonic-gate FALSE); 12567c478bd9Sstevel@tonic-gate 12572f172c55SRobert Thurlow rfs4_clntip_cache_time = 86400 * 365; /* about a year */ 12582f172c55SRobert Thurlow rfs4_clntip_tab = rfs4_table_create(rfs4_server_state, 12592f172c55SRobert Thurlow "ClntIP", 12602f172c55SRobert Thurlow rfs4_clntip_cache_time, 12612f172c55SRobert Thurlow 1, 12622f172c55SRobert Thurlow rfs4_clntip_create, 12632f172c55SRobert Thurlow rfs4_clntip_destroy, 12642f172c55SRobert Thurlow rfs4_clntip_expiry, 12652f172c55SRobert Thurlow sizeof (rfs4_clntip_t), 12662f172c55SRobert Thurlow TABSIZE, 12672f172c55SRobert Thurlow MAXTABSZ, 100); 12682f172c55SRobert Thurlow rfs4_clntip_idx = rfs4_index_create(rfs4_clntip_tab, 12692f172c55SRobert Thurlow "client_ip", clntip_hash, 12702f172c55SRobert Thurlow clntip_compare, clntip_mkkey, 12712f172c55SRobert Thurlow TRUE); 12722f172c55SRobert Thurlow 12737c478bd9Sstevel@tonic-gate rfs4_openowner_cache_time *= rfs4_lease_time; 12747c478bd9Sstevel@tonic-gate rfs4_openowner_tab = rfs4_table_create(rfs4_server_state, 12757c478bd9Sstevel@tonic-gate "OpenOwner", 12767c478bd9Sstevel@tonic-gate rfs4_openowner_cache_time, 12777c478bd9Sstevel@tonic-gate 1, 12787c478bd9Sstevel@tonic-gate rfs4_openowner_create, 12797c478bd9Sstevel@tonic-gate rfs4_openowner_destroy, 12807c478bd9Sstevel@tonic-gate rfs4_openowner_expiry, 12817c478bd9Sstevel@tonic-gate sizeof (rfs4_openowner_t), 12827c478bd9Sstevel@tonic-gate TABSIZE, 12837c478bd9Sstevel@tonic-gate MAXTABSZ, 100); 12847c478bd9Sstevel@tonic-gate rfs4_openowner_idx = rfs4_index_create(rfs4_openowner_tab, 12857c478bd9Sstevel@tonic-gate "open_owner4", openowner_hash, 12867c478bd9Sstevel@tonic-gate openowner_compare, 12877c478bd9Sstevel@tonic-gate openowner_mkkey, TRUE); 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate rfs4_state_cache_time *= rfs4_lease_time; 12907c478bd9Sstevel@tonic-gate rfs4_state_tab = rfs4_table_create(rfs4_server_state, 12917c478bd9Sstevel@tonic-gate "OpenStateID", 12927c478bd9Sstevel@tonic-gate rfs4_state_cache_time, 12937c478bd9Sstevel@tonic-gate 3, 12947c478bd9Sstevel@tonic-gate rfs4_state_create, 12957c478bd9Sstevel@tonic-gate rfs4_state_destroy, 12967c478bd9Sstevel@tonic-gate rfs4_state_expiry, 12977c478bd9Sstevel@tonic-gate sizeof (rfs4_state_t), 12987c478bd9Sstevel@tonic-gate TABSIZE, 12997c478bd9Sstevel@tonic-gate MAXTABSZ, 100); 1300ed57cab9Srg137905 13017c478bd9Sstevel@tonic-gate rfs4_state_owner_file_idx = rfs4_index_create(rfs4_state_tab, 13027c478bd9Sstevel@tonic-gate "Openowner-File", 13037c478bd9Sstevel@tonic-gate state_owner_file_hash, 13047c478bd9Sstevel@tonic-gate state_owner_file_compare, 13057c478bd9Sstevel@tonic-gate state_owner_file_mkkey, TRUE); 1306ed57cab9Srg137905 13077c478bd9Sstevel@tonic-gate rfs4_state_idx = rfs4_index_create(rfs4_state_tab, 13087c478bd9Sstevel@tonic-gate "State-id", state_hash, 13097c478bd9Sstevel@tonic-gate state_compare, state_mkkey, FALSE); 1310ed57cab9Srg137905 13117c478bd9Sstevel@tonic-gate rfs4_state_file_idx = rfs4_index_create(rfs4_state_tab, 13127c478bd9Sstevel@tonic-gate "File", state_file_hash, 13137c478bd9Sstevel@tonic-gate state_file_compare, state_file_mkkey, 13147c478bd9Sstevel@tonic-gate FALSE); 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate rfs4_lo_state_cache_time *= rfs4_lease_time; 13177c478bd9Sstevel@tonic-gate rfs4_lo_state_tab = rfs4_table_create(rfs4_server_state, 13187c478bd9Sstevel@tonic-gate "LockStateID", 13197c478bd9Sstevel@tonic-gate rfs4_lo_state_cache_time, 13207c478bd9Sstevel@tonic-gate 2, 13217c478bd9Sstevel@tonic-gate rfs4_lo_state_create, 13227c478bd9Sstevel@tonic-gate rfs4_lo_state_destroy, 13237c478bd9Sstevel@tonic-gate rfs4_lo_state_expiry, 13247c478bd9Sstevel@tonic-gate sizeof (rfs4_lo_state_t), 13257c478bd9Sstevel@tonic-gate TABSIZE, 13267c478bd9Sstevel@tonic-gate MAXTABSZ, 100); 1327ed57cab9Srg137905 13287c478bd9Sstevel@tonic-gate rfs4_lo_state_owner_idx = rfs4_index_create(rfs4_lo_state_tab, 13297c478bd9Sstevel@tonic-gate "lockownerxstate", 13307c478bd9Sstevel@tonic-gate lo_state_lo_hash, 13317c478bd9Sstevel@tonic-gate lo_state_lo_compare, 13327c478bd9Sstevel@tonic-gate lo_state_lo_mkkey, TRUE); 1333ed57cab9Srg137905 13347c478bd9Sstevel@tonic-gate rfs4_lo_state_idx = rfs4_index_create(rfs4_lo_state_tab, 13357c478bd9Sstevel@tonic-gate "State-id", 13367c478bd9Sstevel@tonic-gate lo_state_hash, lo_state_compare, 13377c478bd9Sstevel@tonic-gate lo_state_mkkey, FALSE); 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate rfs4_lockowner_cache_time *= rfs4_lease_time; 1340ed57cab9Srg137905 13417c478bd9Sstevel@tonic-gate rfs4_lockowner_tab = rfs4_table_create(rfs4_server_state, 13427c478bd9Sstevel@tonic-gate "Lockowner", 13437c478bd9Sstevel@tonic-gate rfs4_lockowner_cache_time, 13447c478bd9Sstevel@tonic-gate 2, 13457c478bd9Sstevel@tonic-gate rfs4_lockowner_create, 13467c478bd9Sstevel@tonic-gate rfs4_lockowner_destroy, 13477c478bd9Sstevel@tonic-gate rfs4_lockowner_expiry, 13487c478bd9Sstevel@tonic-gate sizeof (rfs4_lockowner_t), 13497c478bd9Sstevel@tonic-gate TABSIZE, 13507c478bd9Sstevel@tonic-gate MAXTABSZ, 100); 1351ed57cab9Srg137905 13527c478bd9Sstevel@tonic-gate rfs4_lockowner_idx = rfs4_index_create(rfs4_lockowner_tab, 13537c478bd9Sstevel@tonic-gate "lock_owner4", lockowner_hash, 13547c478bd9Sstevel@tonic-gate lockowner_compare, 13557c478bd9Sstevel@tonic-gate lockowner_mkkey, TRUE); 1356ed57cab9Srg137905 13577c478bd9Sstevel@tonic-gate rfs4_lockowner_pid_idx = rfs4_index_create(rfs4_lockowner_tab, 13587c478bd9Sstevel@tonic-gate "pid", pid_hash, 13597c478bd9Sstevel@tonic-gate pid_compare, pid_mkkey, 13607c478bd9Sstevel@tonic-gate FALSE); 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate rfs4_file_cache_time *= rfs4_lease_time; 13637c478bd9Sstevel@tonic-gate rfs4_file_tab = rfs4_table_create(rfs4_server_state, 13647c478bd9Sstevel@tonic-gate "File", 13657c478bd9Sstevel@tonic-gate rfs4_file_cache_time, 13667c478bd9Sstevel@tonic-gate 1, 13677c478bd9Sstevel@tonic-gate rfs4_file_create, 13687c478bd9Sstevel@tonic-gate rfs4_file_destroy, 13697c478bd9Sstevel@tonic-gate NULL, 13707c478bd9Sstevel@tonic-gate sizeof (rfs4_file_t), 13717c478bd9Sstevel@tonic-gate TABSIZE, 13727c478bd9Sstevel@tonic-gate MAXTABSZ, -1); 1373ed57cab9Srg137905 13747c478bd9Sstevel@tonic-gate rfs4_file_idx = rfs4_index_create(rfs4_file_tab, 13757c478bd9Sstevel@tonic-gate "Filehandle", file_hash, 13767c478bd9Sstevel@tonic-gate file_compare, file_mkkey, TRUE); 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate rfs4_deleg_state_cache_time *= rfs4_lease_time; 13797c478bd9Sstevel@tonic-gate rfs4_deleg_state_tab = rfs4_table_create(rfs4_server_state, 13807c478bd9Sstevel@tonic-gate "DelegStateID", 13817c478bd9Sstevel@tonic-gate rfs4_deleg_state_cache_time, 13827c478bd9Sstevel@tonic-gate 2, 13837c478bd9Sstevel@tonic-gate rfs4_deleg_state_create, 13847c478bd9Sstevel@tonic-gate rfs4_deleg_state_destroy, 13857c478bd9Sstevel@tonic-gate rfs4_deleg_state_expiry, 13867c478bd9Sstevel@tonic-gate sizeof (rfs4_deleg_state_t), 13877c478bd9Sstevel@tonic-gate TABSIZE, 13887c478bd9Sstevel@tonic-gate MAXTABSZ, 100); 13897c478bd9Sstevel@tonic-gate rfs4_deleg_idx = rfs4_index_create(rfs4_deleg_state_tab, 13907c478bd9Sstevel@tonic-gate "DelegByFileClient", 13917c478bd9Sstevel@tonic-gate deleg_hash, 13927c478bd9Sstevel@tonic-gate deleg_compare, 13937c478bd9Sstevel@tonic-gate deleg_mkkey, TRUE); 1394ed57cab9Srg137905 13957c478bd9Sstevel@tonic-gate rfs4_deleg_state_idx = rfs4_index_create(rfs4_deleg_state_tab, 13967c478bd9Sstevel@tonic-gate "DelegState", 13977c478bd9Sstevel@tonic-gate deleg_state_hash, 13987c478bd9Sstevel@tonic-gate deleg_state_compare, 13997c478bd9Sstevel@tonic-gate deleg_state_mkkey, FALSE); 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate /* 14027c478bd9Sstevel@tonic-gate * Init the stable storage. 14037c478bd9Sstevel@tonic-gate */ 14047c478bd9Sstevel@tonic-gate rfs4_ss_init(); 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate rfs4_client_clrst = rfs4_clear_client_state; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate mutex_exit(&rfs4_state_lock); 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate /* 14137c478bd9Sstevel@tonic-gate * Used at server shutdown to cleanup all of the NFSv4 server's structures 14147c478bd9Sstevel@tonic-gate * and other state. 14157c478bd9Sstevel@tonic-gate */ 14167c478bd9Sstevel@tonic-gate void 14177c478bd9Sstevel@tonic-gate rfs4_state_fini() 14187c478bd9Sstevel@tonic-gate { 14197c478bd9Sstevel@tonic-gate rfs4_database_t *dbp; 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate mutex_enter(&rfs4_state_lock); 14227c478bd9Sstevel@tonic-gate 14237c478bd9Sstevel@tonic-gate if (rfs4_server_state == NULL) { 14247c478bd9Sstevel@tonic-gate mutex_exit(&rfs4_state_lock); 14257c478bd9Sstevel@tonic-gate return; 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate rfs4_client_clrst = NULL; 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate rfs4_set_deleg_policy(SRV_NEVER_DELEGATE); 14317c478bd9Sstevel@tonic-gate dbp = rfs4_server_state; 14327c478bd9Sstevel@tonic-gate rfs4_server_state = NULL; 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate /* 14357c478bd9Sstevel@tonic-gate * Cleanup the CPR callback. 14367c478bd9Sstevel@tonic-gate */ 14377c478bd9Sstevel@tonic-gate if (cpr_id) 14387c478bd9Sstevel@tonic-gate (void) callb_delete(cpr_id); 14397c478bd9Sstevel@tonic-gate 14407c478bd9Sstevel@tonic-gate rw_destroy(&rfs4_findclient_lock); 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate /* First stop all of the reaper threads in the database */ 14437c478bd9Sstevel@tonic-gate rfs4_database_shutdown(dbp); 14447c478bd9Sstevel@tonic-gate /* clean up any dangling stable storage structures */ 14457c478bd9Sstevel@tonic-gate rfs4_ss_fini(); 14467c478bd9Sstevel@tonic-gate /* Now actually destroy/release the database and its tables */ 14477c478bd9Sstevel@tonic-gate rfs4_database_destroy(dbp); 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate /* Reset the cache timers for next time */ 14507c478bd9Sstevel@tonic-gate rfs4_client_cache_time = 0; 14517c478bd9Sstevel@tonic-gate rfs4_openowner_cache_time = 0; 14527c478bd9Sstevel@tonic-gate rfs4_state_cache_time = 0; 14537c478bd9Sstevel@tonic-gate rfs4_lo_state_cache_time = 0; 14547c478bd9Sstevel@tonic-gate rfs4_lockowner_cache_time = 0; 14557c478bd9Sstevel@tonic-gate rfs4_file_cache_time = 0; 14567c478bd9Sstevel@tonic-gate rfs4_deleg_state_cache_time = 0; 14577c478bd9Sstevel@tonic-gate 14587c478bd9Sstevel@tonic-gate mutex_exit(&rfs4_state_lock); 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate /* destroy server instances and current instance ptr */ 14617c478bd9Sstevel@tonic-gate rfs4_servinst_destroy_all(); 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate /* reset the "first NFSv4 request" status */ 14647c478bd9Sstevel@tonic-gate rfs4_seen_first_compound = 0; 1465cee86682Scalum 1466cee86682Scalum /* DSS: distributed stable storage */ 1467cee86682Scalum nvlist_free(rfs4_dss_oldpaths); 1468cee86682Scalum nvlist_free(rfs4_dss_paths); 1469cee86682Scalum rfs4_dss_paths = rfs4_dss_oldpaths = NULL; 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate typedef union { 14737c478bd9Sstevel@tonic-gate struct { 14747c478bd9Sstevel@tonic-gate uint32_t start_time; 14757c478bd9Sstevel@tonic-gate uint32_t c_id; 14767c478bd9Sstevel@tonic-gate } impl_id; 14777c478bd9Sstevel@tonic-gate clientid4 id4; 14787c478bd9Sstevel@tonic-gate } cid; 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate static int foreign_stateid(stateid_t *id); 14817c478bd9Sstevel@tonic-gate static int foreign_clientid(cid *cidp); 14827c478bd9Sstevel@tonic-gate static void embed_nodeid(cid *cidp); 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate typedef union { 14857c478bd9Sstevel@tonic-gate struct { 14867c478bd9Sstevel@tonic-gate uint32_t c_id; 14877c478bd9Sstevel@tonic-gate uint32_t gen_num; 14887c478bd9Sstevel@tonic-gate } cv_impl; 14897c478bd9Sstevel@tonic-gate verifier4 confirm_verf; 14907c478bd9Sstevel@tonic-gate } scid_confirm_verf; 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate static uint32_t 14937c478bd9Sstevel@tonic-gate clientid_hash(void *key) 14947c478bd9Sstevel@tonic-gate { 14957c478bd9Sstevel@tonic-gate cid *idp = key; 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate return (idp->impl_id.c_id); 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate static bool_t 15017c478bd9Sstevel@tonic-gate clientid_compare(rfs4_entry_t entry, void *key) 15027c478bd9Sstevel@tonic-gate { 1503d216dff5SRobert Mastors rfs4_client_t *cp = (rfs4_client_t *)entry; 15047c478bd9Sstevel@tonic-gate clientid4 *idp = key; 15057c478bd9Sstevel@tonic-gate 1506d216dff5SRobert Mastors return (*idp == cp->rc_clientid); 15077c478bd9Sstevel@tonic-gate } 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate static void * 15107c478bd9Sstevel@tonic-gate clientid_mkkey(rfs4_entry_t entry) 15117c478bd9Sstevel@tonic-gate { 1512d216dff5SRobert Mastors rfs4_client_t *cp = (rfs4_client_t *)entry; 15137c478bd9Sstevel@tonic-gate 1514d216dff5SRobert Mastors return (&cp->rc_clientid); 15157c478bd9Sstevel@tonic-gate } 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate static uint32_t 15187c478bd9Sstevel@tonic-gate nfsclnt_hash(void *key) 15197c478bd9Sstevel@tonic-gate { 15207c478bd9Sstevel@tonic-gate nfs_client_id4 *client = key; 15217c478bd9Sstevel@tonic-gate int i; 15227c478bd9Sstevel@tonic-gate uint32_t hash = 0; 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate for (i = 0; i < client->id_len; i++) { 15257c478bd9Sstevel@tonic-gate hash <<= 1; 15267c478bd9Sstevel@tonic-gate hash += (uint_t)client->id_val[i]; 15277c478bd9Sstevel@tonic-gate } 15287c478bd9Sstevel@tonic-gate return (hash); 15297c478bd9Sstevel@tonic-gate } 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate static bool_t 15337c478bd9Sstevel@tonic-gate nfsclnt_compare(rfs4_entry_t entry, void *key) 15347c478bd9Sstevel@tonic-gate { 1535d216dff5SRobert Mastors rfs4_client_t *cp = (rfs4_client_t *)entry; 15367c478bd9Sstevel@tonic-gate nfs_client_id4 *nfs_client = key; 15377c478bd9Sstevel@tonic-gate 1538d216dff5SRobert Mastors if (cp->rc_nfs_client.id_len != nfs_client->id_len) 15397c478bd9Sstevel@tonic-gate return (FALSE); 15407c478bd9Sstevel@tonic-gate 1541d216dff5SRobert Mastors return (bcmp(cp->rc_nfs_client.id_val, nfs_client->id_val, 15427c478bd9Sstevel@tonic-gate nfs_client->id_len) == 0); 15437c478bd9Sstevel@tonic-gate } 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate static void * 15467c478bd9Sstevel@tonic-gate nfsclnt_mkkey(rfs4_entry_t entry) 15477c478bd9Sstevel@tonic-gate { 1548d216dff5SRobert Mastors rfs4_client_t *cp = (rfs4_client_t *)entry; 15497c478bd9Sstevel@tonic-gate 1550d216dff5SRobert Mastors return (&cp->rc_nfs_client); 15517c478bd9Sstevel@tonic-gate } 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate static bool_t 15547c478bd9Sstevel@tonic-gate rfs4_client_expiry(rfs4_entry_t u_entry) 15557c478bd9Sstevel@tonic-gate { 15567c478bd9Sstevel@tonic-gate rfs4_client_t *cp = (rfs4_client_t *)u_entry; 15577c478bd9Sstevel@tonic-gate bool_t cp_expired; 15587c478bd9Sstevel@tonic-gate 1559fbd8dcf9SGerald Thornbrugh if (rfs4_dbe_is_invalid(cp->rc_dbe)) { 1560fbd8dcf9SGerald Thornbrugh cp->rc_ss_remove = 1; 15617c478bd9Sstevel@tonic-gate return (TRUE); 1562fbd8dcf9SGerald Thornbrugh } 15637c478bd9Sstevel@tonic-gate /* 15647c478bd9Sstevel@tonic-gate * If the sysadmin has used clear_locks for this 15657c478bd9Sstevel@tonic-gate * entry then forced_expire will be set and we 15667c478bd9Sstevel@tonic-gate * want this entry to be reaped. Or the entry 15677c478bd9Sstevel@tonic-gate * has exceeded its lease period. 15687c478bd9Sstevel@tonic-gate */ 1569d216dff5SRobert Mastors cp_expired = (cp->rc_forced_expire || 1570d216dff5SRobert Mastors (gethrestime_sec() - cp->rc_last_access 15717c478bd9Sstevel@tonic-gate > rfs4_lease_time)); 1572cee86682Scalum 1573d216dff5SRobert Mastors if (!cp->rc_ss_remove && cp_expired) 1574d216dff5SRobert Mastors cp->rc_ss_remove = 1; 15757c478bd9Sstevel@tonic-gate return (cp_expired); 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate 1578cee86682Scalum /* 1579cee86682Scalum * Remove the leaf file from all distributed stable storage paths. 1580cee86682Scalum */ 1581cee86682Scalum static void 1582cee86682Scalum rfs4_dss_remove_cpleaf(rfs4_client_t *cp) 1583cee86682Scalum { 1584fbd8dcf9SGerald Thornbrugh rfs4_servinst_t *sip; 1585d216dff5SRobert Mastors char *leaf = cp->rc_ss_pn->leaf; 1586cee86682Scalum 1587fbd8dcf9SGerald Thornbrugh /* 1588fbd8dcf9SGerald Thornbrugh * since the state files are written to all DSS 1589fbd8dcf9SGerald Thornbrugh * paths we must remove this leaf file instance 1590fbd8dcf9SGerald Thornbrugh * from all server instances. 1591fbd8dcf9SGerald Thornbrugh */ 1592fbd8dcf9SGerald Thornbrugh 1593fbd8dcf9SGerald Thornbrugh mutex_enter(&rfs4_servinst_lock); 1594fbd8dcf9SGerald Thornbrugh for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev) { 1595fbd8dcf9SGerald Thornbrugh /* remove the leaf file associated with this server instance */ 1596fbd8dcf9SGerald Thornbrugh rfs4_dss_remove_leaf(sip, NFS4_DSS_STATE_LEAF, leaf); 1597fbd8dcf9SGerald Thornbrugh } 1598fbd8dcf9SGerald Thornbrugh mutex_exit(&rfs4_servinst_lock); 1599cee86682Scalum } 1600cee86682Scalum 1601cee86682Scalum static void 1602cee86682Scalum rfs4_dss_remove_leaf(rfs4_servinst_t *sip, char *dir_leaf, char *leaf) 1603cee86682Scalum { 1604cee86682Scalum int i, npaths = sip->dss_npaths; 1605cee86682Scalum 1606cee86682Scalum for (i = 0; i < npaths; i++) { 1607cee86682Scalum rfs4_dss_path_t *dss_path = sip->dss_paths[i]; 1608cee86682Scalum char *path, *dir; 1609cee86682Scalum size_t pathlen; 1610cee86682Scalum 1611cee86682Scalum /* the HA-NFSv4 path might have been failed-over away from us */ 1612cee86682Scalum if (dss_path == NULL) 1613cee86682Scalum continue; 1614cee86682Scalum 1615cee86682Scalum dir = dss_path->path; 1616cee86682Scalum 1617cee86682Scalum /* allow 3 extra bytes for two '/' & a NUL */ 1618cee86682Scalum pathlen = strlen(dir) + strlen(dir_leaf) + strlen(leaf) + 3; 1619cee86682Scalum path = kmem_alloc(pathlen, KM_SLEEP); 1620cee86682Scalum (void) sprintf(path, "%s/%s/%s", dir, dir_leaf, leaf); 1621cee86682Scalum 1622cee86682Scalum (void) vn_remove(path, UIO_SYSSPACE, RMFILE); 1623cee86682Scalum 1624cee86682Scalum kmem_free(path, pathlen); 1625cee86682Scalum } 1626cee86682Scalum } 1627cee86682Scalum 16287c478bd9Sstevel@tonic-gate static void 16297c478bd9Sstevel@tonic-gate rfs4_client_destroy(rfs4_entry_t u_entry) 16307c478bd9Sstevel@tonic-gate { 16317c478bd9Sstevel@tonic-gate rfs4_client_t *cp = (rfs4_client_t *)u_entry; 16327c478bd9Sstevel@tonic-gate 1633d216dff5SRobert Mastors mutex_destroy(cp->rc_cbinfo.cb_lock); 1634d216dff5SRobert Mastors cv_destroy(cp->rc_cbinfo.cb_cv); 1635d216dff5SRobert Mastors cv_destroy(cp->rc_cbinfo.cb_cv_nullcaller); 1636d216dff5SRobert Mastors list_destroy(&cp->rc_openownerlist); 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate /* free callback info */ 1639d216dff5SRobert Mastors rfs4_cbinfo_free(&cp->rc_cbinfo); 16407c478bd9Sstevel@tonic-gate 1641d216dff5SRobert Mastors if (cp->rc_cp_confirmed) 1642d216dff5SRobert Mastors rfs4_client_rele(cp->rc_cp_confirmed); 16437c478bd9Sstevel@tonic-gate 1644d216dff5SRobert Mastors if (cp->rc_ss_pn) { 1645cee86682Scalum /* check if the stable storage files need to be removed */ 1646d216dff5SRobert Mastors if (cp->rc_ss_remove) 1647cee86682Scalum rfs4_dss_remove_cpleaf(cp); 1648d216dff5SRobert Mastors rfs4_ss_pnfree(cp->rc_ss_pn); 16497c478bd9Sstevel@tonic-gate } 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate /* Free the client supplied client id */ 1652d216dff5SRobert Mastors kmem_free(cp->rc_nfs_client.id_val, cp->rc_nfs_client.id_len); 16537c478bd9Sstevel@tonic-gate 1654d216dff5SRobert Mastors if (cp->rc_sysidt != LM_NOSYSID) 1655d216dff5SRobert Mastors lm_free_sysidt(cp->rc_sysidt); 16567c478bd9Sstevel@tonic-gate } 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate static bool_t 16597c478bd9Sstevel@tonic-gate rfs4_client_create(rfs4_entry_t u_entry, void *arg) 16607c478bd9Sstevel@tonic-gate { 16617c478bd9Sstevel@tonic-gate rfs4_client_t *cp = (rfs4_client_t *)u_entry; 16627c478bd9Sstevel@tonic-gate nfs_client_id4 *client = (nfs_client_id4 *)arg; 16632f172c55SRobert Thurlow struct sockaddr *ca; 16647c478bd9Sstevel@tonic-gate cid *cidp; 16657c478bd9Sstevel@tonic-gate scid_confirm_verf *scvp; 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate /* Get a clientid to give to the client */ 1668d216dff5SRobert Mastors cidp = (cid *)&cp->rc_clientid; 16697c478bd9Sstevel@tonic-gate cidp->impl_id.start_time = rfs4_start_time; 1670d216dff5SRobert Mastors cidp->impl_id.c_id = (uint32_t)rfs4_dbe_getid(cp->rc_dbe); 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate /* If we are booted as a cluster node, embed our nodeid */ 16737c478bd9Sstevel@tonic-gate if (cluster_bootflags & CLUSTER_BOOTED) 16747c478bd9Sstevel@tonic-gate embed_nodeid(cidp); 16757c478bd9Sstevel@tonic-gate 16767c478bd9Sstevel@tonic-gate /* Allocate and copy client's client id value */ 1677d216dff5SRobert Mastors cp->rc_nfs_client.id_val = kmem_alloc(client->id_len, KM_SLEEP); 1678d216dff5SRobert Mastors cp->rc_nfs_client.id_len = client->id_len; 1679d216dff5SRobert Mastors bcopy(client->id_val, cp->rc_nfs_client.id_val, client->id_len); 1680d216dff5SRobert Mastors cp->rc_nfs_client.verifier = client->verifier; 16817c478bd9Sstevel@tonic-gate 16822f172c55SRobert Thurlow /* Copy client's IP address */ 16832f172c55SRobert Thurlow ca = client->cl_addr; 16842f172c55SRobert Thurlow if (ca->sa_family == AF_INET) 16852f172c55SRobert Thurlow bcopy(ca, &cp->rc_addr, sizeof (struct sockaddr_in)); 16862f172c55SRobert Thurlow else if (ca->sa_family == AF_INET6) 16872f172c55SRobert Thurlow bcopy(ca, &cp->rc_addr, sizeof (struct sockaddr_in6)); 16882f172c55SRobert Thurlow cp->rc_nfs_client.cl_addr = (struct sockaddr *)&cp->rc_addr; 16892f172c55SRobert Thurlow 16907c478bd9Sstevel@tonic-gate /* Init the value for the SETCLIENTID_CONFIRM verifier */ 1691d216dff5SRobert Mastors scvp = (scid_confirm_verf *)&cp->rc_confirm_verf; 16927c478bd9Sstevel@tonic-gate scvp->cv_impl.c_id = cidp->impl_id.c_id; 16937c478bd9Sstevel@tonic-gate scvp->cv_impl.gen_num = 0; 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate /* An F_UNLKSYS has been done for this client */ 1696d216dff5SRobert Mastors cp->rc_unlksys_completed = FALSE; 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate /* We need the client to ack us */ 1699d216dff5SRobert Mastors cp->rc_need_confirm = TRUE; 1700d216dff5SRobert Mastors cp->rc_cp_confirmed = NULL; 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate /* TRUE all the time until the callback path actually fails */ 1703d216dff5SRobert Mastors cp->rc_cbinfo.cb_notified_of_cb_path_down = TRUE; 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate /* Initialize the access time to now */ 1706d216dff5SRobert Mastors cp->rc_last_access = gethrestime_sec(); 17077c478bd9Sstevel@tonic-gate 1708d216dff5SRobert Mastors cp->rc_cr_set = NULL; 17097c478bd9Sstevel@tonic-gate 1710d216dff5SRobert Mastors cp->rc_sysidt = LM_NOSYSID; 17117c478bd9Sstevel@tonic-gate 1712d216dff5SRobert Mastors list_create(&cp->rc_openownerlist, sizeof (rfs4_openowner_t), 1713d216dff5SRobert Mastors offsetof(rfs4_openowner_t, ro_node)); 17147c478bd9Sstevel@tonic-gate 17157c478bd9Sstevel@tonic-gate /* set up the callback control structure */ 1716d216dff5SRobert Mastors cp->rc_cbinfo.cb_state = CB_UNINIT; 1717d216dff5SRobert Mastors mutex_init(cp->rc_cbinfo.cb_lock, NULL, MUTEX_DEFAULT, NULL); 1718d216dff5SRobert Mastors cv_init(cp->rc_cbinfo.cb_cv, NULL, CV_DEFAULT, NULL); 1719d216dff5SRobert Mastors cv_init(cp->rc_cbinfo.cb_cv_nullcaller, NULL, CV_DEFAULT, NULL); 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate /* 17227c478bd9Sstevel@tonic-gate * Associate the client_t with the current server instance. 17237c478bd9Sstevel@tonic-gate * The hold is solely to satisfy the calling requirement of 17247c478bd9Sstevel@tonic-gate * rfs4_servinst_assign(). In this case it's not strictly necessary. 17257c478bd9Sstevel@tonic-gate */ 1726d216dff5SRobert Mastors rfs4_dbe_hold(cp->rc_dbe); 17277c478bd9Sstevel@tonic-gate rfs4_servinst_assign(cp, rfs4_cur_servinst); 1728d216dff5SRobert Mastors rfs4_dbe_rele(cp->rc_dbe); 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate return (TRUE); 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate 17337c478bd9Sstevel@tonic-gate /* 17347c478bd9Sstevel@tonic-gate * Caller wants to generate/update the setclientid_confirm verifier 17357c478bd9Sstevel@tonic-gate * associated with a client. This is done during the SETCLIENTID 17367c478bd9Sstevel@tonic-gate * processing. 17377c478bd9Sstevel@tonic-gate */ 17387c478bd9Sstevel@tonic-gate void 17397c478bd9Sstevel@tonic-gate rfs4_client_scv_next(rfs4_client_t *cp) 17407c478bd9Sstevel@tonic-gate { 17417c478bd9Sstevel@tonic-gate scid_confirm_verf *scvp; 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate /* Init the value for the SETCLIENTID_CONFIRM verifier */ 1744d216dff5SRobert Mastors scvp = (scid_confirm_verf *)&cp->rc_confirm_verf; 17457c478bd9Sstevel@tonic-gate scvp->cv_impl.gen_num++; 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate void 17497c478bd9Sstevel@tonic-gate rfs4_client_rele(rfs4_client_t *cp) 17507c478bd9Sstevel@tonic-gate { 1751d216dff5SRobert Mastors rfs4_dbe_rele(cp->rc_dbe); 17527c478bd9Sstevel@tonic-gate } 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate rfs4_client_t * 17557c478bd9Sstevel@tonic-gate rfs4_findclient(nfs_client_id4 *client, bool_t *create, rfs4_client_t *oldcp) 17567c478bd9Sstevel@tonic-gate { 17577c478bd9Sstevel@tonic-gate rfs4_client_t *cp; 17587c478bd9Sstevel@tonic-gate 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate if (oldcp) { 17617c478bd9Sstevel@tonic-gate rw_enter(&rfs4_findclient_lock, RW_WRITER); 1762d216dff5SRobert Mastors rfs4_dbe_hide(oldcp->rc_dbe); 17637c478bd9Sstevel@tonic-gate } else { 17647c478bd9Sstevel@tonic-gate rw_enter(&rfs4_findclient_lock, RW_READER); 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate cp = (rfs4_client_t *)rfs4_dbsearch(rfs4_nfsclnt_idx, client, 17687c478bd9Sstevel@tonic-gate create, (void *)client, RFS4_DBS_VALID); 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate if (oldcp) 1771d216dff5SRobert Mastors rfs4_dbe_unhide(oldcp->rc_dbe); 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate rw_exit(&rfs4_findclient_lock); 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate return (cp); 17767c478bd9Sstevel@tonic-gate } 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate rfs4_client_t * 17797c478bd9Sstevel@tonic-gate rfs4_findclient_by_id(clientid4 clientid, bool_t find_unconfirmed) 17807c478bd9Sstevel@tonic-gate { 17817c478bd9Sstevel@tonic-gate rfs4_client_t *cp; 17827c478bd9Sstevel@tonic-gate bool_t create = FALSE; 17837c478bd9Sstevel@tonic-gate cid *cidp = (cid *)&clientid; 17847c478bd9Sstevel@tonic-gate 17857c478bd9Sstevel@tonic-gate /* If we're a cluster and the nodeid isn't right, short-circuit */ 17867c478bd9Sstevel@tonic-gate if (cluster_bootflags & CLUSTER_BOOTED && foreign_clientid(cidp)) 17877c478bd9Sstevel@tonic-gate return (NULL); 17887c478bd9Sstevel@tonic-gate 17897c478bd9Sstevel@tonic-gate rw_enter(&rfs4_findclient_lock, RW_READER); 17907c478bd9Sstevel@tonic-gate 17917c478bd9Sstevel@tonic-gate cp = (rfs4_client_t *)rfs4_dbsearch(rfs4_clientid_idx, &clientid, 17927c478bd9Sstevel@tonic-gate &create, NULL, RFS4_DBS_VALID); 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate rw_exit(&rfs4_findclient_lock); 17957c478bd9Sstevel@tonic-gate 1796d216dff5SRobert Mastors if (cp && cp->rc_need_confirm && find_unconfirmed == FALSE) { 17977c478bd9Sstevel@tonic-gate rfs4_client_rele(cp); 17987c478bd9Sstevel@tonic-gate return (NULL); 17997c478bd9Sstevel@tonic-gate } else { 18007c478bd9Sstevel@tonic-gate return (cp); 18017c478bd9Sstevel@tonic-gate } 18027c478bd9Sstevel@tonic-gate } 18037c478bd9Sstevel@tonic-gate 18042f172c55SRobert Thurlow static uint32_t 18052f172c55SRobert Thurlow clntip_hash(void *key) 18062f172c55SRobert Thurlow { 18072f172c55SRobert Thurlow struct sockaddr *addr = key; 18082f172c55SRobert Thurlow int i, len = 0; 18092f172c55SRobert Thurlow uint32_t hash = 0; 1810fab83d6aSRobert Thurlow char *ptr; 18112f172c55SRobert Thurlow 1812fab83d6aSRobert Thurlow if (addr->sa_family == AF_INET) { 1813fab83d6aSRobert Thurlow struct sockaddr_in *a = (struct sockaddr_in *)addr; 1814fab83d6aSRobert Thurlow len = sizeof (struct in_addr); 1815fab83d6aSRobert Thurlow ptr = (char *)&a->sin_addr; 1816fab83d6aSRobert Thurlow } else if (addr->sa_family == AF_INET6) { 1817fab83d6aSRobert Thurlow struct sockaddr_in6 *a = (struct sockaddr_in6 *)addr; 1818fab83d6aSRobert Thurlow len = sizeof (struct in6_addr); 1819fab83d6aSRobert Thurlow ptr = (char *)&a->sin6_addr; 1820fab83d6aSRobert Thurlow } else 1821fab83d6aSRobert Thurlow return (0); 18222f172c55SRobert Thurlow 18232f172c55SRobert Thurlow for (i = 0; i < len; i++) { 18242f172c55SRobert Thurlow hash <<= 1; 1825fab83d6aSRobert Thurlow hash += (uint_t)ptr[i]; 18262f172c55SRobert Thurlow } 18272f172c55SRobert Thurlow return (hash); 18282f172c55SRobert Thurlow } 18292f172c55SRobert Thurlow 18302f172c55SRobert Thurlow static bool_t 18312f172c55SRobert Thurlow clntip_compare(rfs4_entry_t entry, void *key) 18322f172c55SRobert Thurlow { 18332f172c55SRobert Thurlow rfs4_clntip_t *cp = (rfs4_clntip_t *)entry; 18342f172c55SRobert Thurlow struct sockaddr *addr = key; 18352f172c55SRobert Thurlow int len = 0; 1836fab83d6aSRobert Thurlow char *p1, *p2; 18372f172c55SRobert Thurlow 1838fab83d6aSRobert Thurlow if (addr->sa_family == AF_INET) { 1839fab83d6aSRobert Thurlow struct sockaddr_in *a1 = (struct sockaddr_in *)&cp->ri_addr; 1840fab83d6aSRobert Thurlow struct sockaddr_in *a2 = (struct sockaddr_in *)addr; 1841fab83d6aSRobert Thurlow len = sizeof (struct in_addr); 1842fab83d6aSRobert Thurlow p1 = (char *)&a1->sin_addr; 1843fab83d6aSRobert Thurlow p2 = (char *)&a2->sin_addr; 1844fab83d6aSRobert Thurlow } else if (addr->sa_family == AF_INET6) { 1845fab83d6aSRobert Thurlow struct sockaddr_in6 *a1 = (struct sockaddr_in6 *)&cp->ri_addr; 1846fab83d6aSRobert Thurlow struct sockaddr_in6 *a2 = (struct sockaddr_in6 *)addr; 1847fab83d6aSRobert Thurlow len = sizeof (struct in6_addr); 1848fab83d6aSRobert Thurlow p1 = (char *)&a1->sin6_addr; 1849fab83d6aSRobert Thurlow p2 = (char *)&a2->sin6_addr; 1850fab83d6aSRobert Thurlow } else 18512f172c55SRobert Thurlow return (0); 18522f172c55SRobert Thurlow 1853fab83d6aSRobert Thurlow return (bcmp(p1, p2, len) == 0); 18542f172c55SRobert Thurlow } 18552f172c55SRobert Thurlow 18562f172c55SRobert Thurlow static void * 18572f172c55SRobert Thurlow clntip_mkkey(rfs4_entry_t entry) 18582f172c55SRobert Thurlow { 18592f172c55SRobert Thurlow rfs4_clntip_t *cp = (rfs4_clntip_t *)entry; 18602f172c55SRobert Thurlow 18612f172c55SRobert Thurlow return (&cp->ri_addr); 18622f172c55SRobert Thurlow } 18632f172c55SRobert Thurlow 18642f172c55SRobert Thurlow static bool_t 18652f172c55SRobert Thurlow rfs4_clntip_expiry(rfs4_entry_t u_entry) 18662f172c55SRobert Thurlow { 18672f172c55SRobert Thurlow rfs4_clntip_t *cp = (rfs4_clntip_t *)u_entry; 18682f172c55SRobert Thurlow 18692f172c55SRobert Thurlow if (rfs4_dbe_is_invalid(cp->ri_dbe)) 18702f172c55SRobert Thurlow return (TRUE); 18712f172c55SRobert Thurlow return (FALSE); 18722f172c55SRobert Thurlow } 18732f172c55SRobert Thurlow 18742f172c55SRobert Thurlow /* ARGSUSED */ 18752f172c55SRobert Thurlow static void 18762f172c55SRobert Thurlow rfs4_clntip_destroy(rfs4_entry_t u_entry) 18772f172c55SRobert Thurlow { 18782f172c55SRobert Thurlow } 18792f172c55SRobert Thurlow 18802f172c55SRobert Thurlow static bool_t 18812f172c55SRobert Thurlow rfs4_clntip_create(rfs4_entry_t u_entry, void *arg) 18822f172c55SRobert Thurlow { 18832f172c55SRobert Thurlow rfs4_clntip_t *cp = (rfs4_clntip_t *)u_entry; 18842f172c55SRobert Thurlow struct sockaddr *ca = (struct sockaddr *)arg; 18852f172c55SRobert Thurlow 18862f172c55SRobert Thurlow /* Copy client's IP address */ 18872f172c55SRobert Thurlow if (ca->sa_family == AF_INET) 18882f172c55SRobert Thurlow bcopy(ca, &cp->ri_addr, sizeof (struct sockaddr_in)); 18892f172c55SRobert Thurlow else if (ca->sa_family == AF_INET6) 18902f172c55SRobert Thurlow bcopy(ca, &cp->ri_addr, sizeof (struct sockaddr_in6)); 18912f172c55SRobert Thurlow else 18922f172c55SRobert Thurlow return (FALSE); 18932f172c55SRobert Thurlow cp->ri_no_referrals = 1; 18942f172c55SRobert Thurlow 18952f172c55SRobert Thurlow return (TRUE); 18962f172c55SRobert Thurlow } 18972f172c55SRobert Thurlow 18982f172c55SRobert Thurlow rfs4_clntip_t * 18992f172c55SRobert Thurlow rfs4_find_clntip(struct sockaddr *addr, bool_t *create) 19002f172c55SRobert Thurlow { 19012f172c55SRobert Thurlow rfs4_clntip_t *cp; 19022f172c55SRobert Thurlow 19032f172c55SRobert Thurlow rw_enter(&rfs4_findclient_lock, RW_READER); 19042f172c55SRobert Thurlow 19052f172c55SRobert Thurlow cp = (rfs4_clntip_t *)rfs4_dbsearch(rfs4_clntip_idx, addr, 19062f172c55SRobert Thurlow create, addr, RFS4_DBS_VALID); 19072f172c55SRobert Thurlow 19082f172c55SRobert Thurlow rw_exit(&rfs4_findclient_lock); 19092f172c55SRobert Thurlow 19102f172c55SRobert Thurlow return (cp); 19112f172c55SRobert Thurlow } 19122f172c55SRobert Thurlow 19132f172c55SRobert Thurlow void 19142f172c55SRobert Thurlow rfs4_invalidate_clntip(struct sockaddr *addr) 19152f172c55SRobert Thurlow { 19162f172c55SRobert Thurlow rfs4_clntip_t *cp; 19172f172c55SRobert Thurlow bool_t create = FALSE; 19182f172c55SRobert Thurlow 19192f172c55SRobert Thurlow rw_enter(&rfs4_findclient_lock, RW_READER); 19202f172c55SRobert Thurlow 19212f172c55SRobert Thurlow cp = (rfs4_clntip_t *)rfs4_dbsearch(rfs4_clntip_idx, addr, 19222f172c55SRobert Thurlow &create, NULL, RFS4_DBS_VALID); 19232f172c55SRobert Thurlow if (cp == NULL) { 19242f172c55SRobert Thurlow rw_exit(&rfs4_findclient_lock); 19252f172c55SRobert Thurlow return; 19262f172c55SRobert Thurlow } 19272f172c55SRobert Thurlow rfs4_dbe_invalidate(cp->ri_dbe); 19282f172c55SRobert Thurlow rfs4_dbe_rele(cp->ri_dbe); 19292f172c55SRobert Thurlow 19302f172c55SRobert Thurlow rw_exit(&rfs4_findclient_lock); 19312f172c55SRobert Thurlow } 19322f172c55SRobert Thurlow 19337c478bd9Sstevel@tonic-gate bool_t 19347c478bd9Sstevel@tonic-gate rfs4_lease_expired(rfs4_client_t *cp) 19357c478bd9Sstevel@tonic-gate { 19367c478bd9Sstevel@tonic-gate bool_t rc; 19377c478bd9Sstevel@tonic-gate 1938d216dff5SRobert Mastors rfs4_dbe_lock(cp->rc_dbe); 19397c478bd9Sstevel@tonic-gate 19407c478bd9Sstevel@tonic-gate /* 19417c478bd9Sstevel@tonic-gate * If the admin has executed clear_locks for this 19427c478bd9Sstevel@tonic-gate * client id, force expire will be set, so no need 19437c478bd9Sstevel@tonic-gate * to calculate anything because it's "outa here". 19447c478bd9Sstevel@tonic-gate */ 1945d216dff5SRobert Mastors if (cp->rc_forced_expire) { 19467c478bd9Sstevel@tonic-gate rc = TRUE; 19477c478bd9Sstevel@tonic-gate } else { 1948d216dff5SRobert Mastors rc = (gethrestime_sec() - cp->rc_last_access > rfs4_lease_time); 19497c478bd9Sstevel@tonic-gate } 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate /* 19527c478bd9Sstevel@tonic-gate * If the lease has expired we will also want 19537c478bd9Sstevel@tonic-gate * to remove any stable storage state data. So 19547c478bd9Sstevel@tonic-gate * mark the client id accordingly. 19557c478bd9Sstevel@tonic-gate */ 1956d216dff5SRobert Mastors if (!cp->rc_ss_remove) 1957d216dff5SRobert Mastors cp->rc_ss_remove = (rc == TRUE); 19587c478bd9Sstevel@tonic-gate 1959d216dff5SRobert Mastors rfs4_dbe_unlock(cp->rc_dbe); 19607c478bd9Sstevel@tonic-gate 19617c478bd9Sstevel@tonic-gate return (rc); 19627c478bd9Sstevel@tonic-gate } 19637c478bd9Sstevel@tonic-gate 19647c478bd9Sstevel@tonic-gate void 19657c478bd9Sstevel@tonic-gate rfs4_update_lease(rfs4_client_t *cp) 19667c478bd9Sstevel@tonic-gate { 1967d216dff5SRobert Mastors rfs4_dbe_lock(cp->rc_dbe); 1968d216dff5SRobert Mastors if (!cp->rc_forced_expire) 1969d216dff5SRobert Mastors cp->rc_last_access = gethrestime_sec(); 1970d216dff5SRobert Mastors rfs4_dbe_unlock(cp->rc_dbe); 19717c478bd9Sstevel@tonic-gate } 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate 19747c478bd9Sstevel@tonic-gate static bool_t 19757c478bd9Sstevel@tonic-gate EQOPENOWNER(open_owner4 *a, open_owner4 *b) 19767c478bd9Sstevel@tonic-gate { 19777c478bd9Sstevel@tonic-gate bool_t rc; 19787c478bd9Sstevel@tonic-gate 19797c478bd9Sstevel@tonic-gate if (a->clientid != b->clientid) 19807c478bd9Sstevel@tonic-gate return (FALSE); 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate if (a->owner_len != b->owner_len) 19837c478bd9Sstevel@tonic-gate return (FALSE); 19847c478bd9Sstevel@tonic-gate 19857c478bd9Sstevel@tonic-gate rc = (bcmp(a->owner_val, b->owner_val, a->owner_len) == 0); 19867c478bd9Sstevel@tonic-gate 19877c478bd9Sstevel@tonic-gate return (rc); 19887c478bd9Sstevel@tonic-gate } 19897c478bd9Sstevel@tonic-gate 19907c478bd9Sstevel@tonic-gate static uint_t 19917c478bd9Sstevel@tonic-gate openowner_hash(void *key) 19927c478bd9Sstevel@tonic-gate { 19937c478bd9Sstevel@tonic-gate int i; 19947c478bd9Sstevel@tonic-gate open_owner4 *openowner = key; 19957c478bd9Sstevel@tonic-gate uint_t hash = 0; 19967c478bd9Sstevel@tonic-gate 19977c478bd9Sstevel@tonic-gate for (i = 0; i < openowner->owner_len; i++) { 19987c478bd9Sstevel@tonic-gate hash <<= 4; 19997c478bd9Sstevel@tonic-gate hash += (uint_t)openowner->owner_val[i]; 20007c478bd9Sstevel@tonic-gate } 20017c478bd9Sstevel@tonic-gate hash += (uint_t)openowner->clientid; 20027c478bd9Sstevel@tonic-gate hash |= (openowner->clientid >> 32); 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate return (hash); 20057c478bd9Sstevel@tonic-gate } 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate static bool_t 20087c478bd9Sstevel@tonic-gate openowner_compare(rfs4_entry_t u_entry, void *key) 20097c478bd9Sstevel@tonic-gate { 2010d216dff5SRobert Mastors rfs4_openowner_t *oo = (rfs4_openowner_t *)u_entry; 20117c478bd9Sstevel@tonic-gate open_owner4 *arg = key; 20127c478bd9Sstevel@tonic-gate 2013d216dff5SRobert Mastors return (EQOPENOWNER(&oo->ro_owner, arg)); 20147c478bd9Sstevel@tonic-gate } 20157c478bd9Sstevel@tonic-gate 20167c478bd9Sstevel@tonic-gate void * 20177c478bd9Sstevel@tonic-gate openowner_mkkey(rfs4_entry_t u_entry) 20187c478bd9Sstevel@tonic-gate { 2019d216dff5SRobert Mastors rfs4_openowner_t *oo = (rfs4_openowner_t *)u_entry; 20207c478bd9Sstevel@tonic-gate 2021d216dff5SRobert Mastors return (&oo->ro_owner); 20227c478bd9Sstevel@tonic-gate } 20237c478bd9Sstevel@tonic-gate 2024afb25078SVitaliy Gusev /* ARGSUSED */ 20257c478bd9Sstevel@tonic-gate static bool_t 20267c478bd9Sstevel@tonic-gate rfs4_openowner_expiry(rfs4_entry_t u_entry) 20277c478bd9Sstevel@tonic-gate { 2028afb25078SVitaliy Gusev /* openstateid held us and did all needed delay */ 20297c478bd9Sstevel@tonic-gate return (TRUE); 20307c478bd9Sstevel@tonic-gate } 20317c478bd9Sstevel@tonic-gate 20327c478bd9Sstevel@tonic-gate static void 20337c478bd9Sstevel@tonic-gate rfs4_openowner_destroy(rfs4_entry_t u_entry) 20347c478bd9Sstevel@tonic-gate { 2035d216dff5SRobert Mastors rfs4_openowner_t *oo = (rfs4_openowner_t *)u_entry; 20367c478bd9Sstevel@tonic-gate 20377c478bd9Sstevel@tonic-gate /* Remove open owner from client's lists of open owners */ 2038d216dff5SRobert Mastors rfs4_dbe_lock(oo->ro_client->rc_dbe); 2039d216dff5SRobert Mastors list_remove(&oo->ro_client->rc_openownerlist, oo); 2040d216dff5SRobert Mastors rfs4_dbe_unlock(oo->ro_client->rc_dbe); 20417c478bd9Sstevel@tonic-gate 20427c478bd9Sstevel@tonic-gate /* One less reference to the client */ 2043d216dff5SRobert Mastors rfs4_client_rele(oo->ro_client); 2044d216dff5SRobert Mastors oo->ro_client = NULL; 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate /* Free the last reply for this lock owner */ 2047d216dff5SRobert Mastors rfs4_free_reply(&oo->ro_reply); 20487c478bd9Sstevel@tonic-gate 2049d216dff5SRobert Mastors if (oo->ro_reply_fh.nfs_fh4_val) { 2050d216dff5SRobert Mastors kmem_free(oo->ro_reply_fh.nfs_fh4_val, 2051d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_len); 2052d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_val = NULL; 2053d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_len = 0; 20547c478bd9Sstevel@tonic-gate } 20557c478bd9Sstevel@tonic-gate 2056d216dff5SRobert Mastors rfs4_sw_destroy(&oo->ro_sw); 2057d216dff5SRobert Mastors list_destroy(&oo->ro_statelist); 2058d216dff5SRobert Mastors 20597c478bd9Sstevel@tonic-gate /* Free the lock owner id */ 2060d216dff5SRobert Mastors kmem_free(oo->ro_owner.owner_val, oo->ro_owner.owner_len); 20617c478bd9Sstevel@tonic-gate } 20627c478bd9Sstevel@tonic-gate 20637c478bd9Sstevel@tonic-gate void 2064d216dff5SRobert Mastors rfs4_openowner_rele(rfs4_openowner_t *oo) 20657c478bd9Sstevel@tonic-gate { 2066d216dff5SRobert Mastors rfs4_dbe_rele(oo->ro_dbe); 20677c478bd9Sstevel@tonic-gate } 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate static bool_t 20707c478bd9Sstevel@tonic-gate rfs4_openowner_create(rfs4_entry_t u_entry, void *arg) 20717c478bd9Sstevel@tonic-gate { 2072d216dff5SRobert Mastors rfs4_openowner_t *oo = (rfs4_openowner_t *)u_entry; 20737c478bd9Sstevel@tonic-gate rfs4_openowner_t *argp = (rfs4_openowner_t *)arg; 2074d216dff5SRobert Mastors open_owner4 *openowner = &argp->ro_owner; 2075d216dff5SRobert Mastors seqid4 seqid = argp->ro_open_seqid; 20767c478bd9Sstevel@tonic-gate rfs4_client_t *cp; 20777c478bd9Sstevel@tonic-gate bool_t create = FALSE; 20787c478bd9Sstevel@tonic-gate 20797c478bd9Sstevel@tonic-gate rw_enter(&rfs4_findclient_lock, RW_READER); 20807c478bd9Sstevel@tonic-gate 20817c478bd9Sstevel@tonic-gate cp = (rfs4_client_t *)rfs4_dbsearch(rfs4_clientid_idx, 20827c478bd9Sstevel@tonic-gate &openowner->clientid, 20837c478bd9Sstevel@tonic-gate &create, NULL, RFS4_DBS_VALID); 20847c478bd9Sstevel@tonic-gate 20857c478bd9Sstevel@tonic-gate rw_exit(&rfs4_findclient_lock); 20867c478bd9Sstevel@tonic-gate 20877c478bd9Sstevel@tonic-gate if (cp == NULL) 20887c478bd9Sstevel@tonic-gate return (FALSE); 20897c478bd9Sstevel@tonic-gate 2090d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_len = 0; 2091d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_val = NULL; 20927c478bd9Sstevel@tonic-gate 2093d216dff5SRobert Mastors oo->ro_owner.clientid = openowner->clientid; 2094d216dff5SRobert Mastors oo->ro_owner.owner_val = 20957c478bd9Sstevel@tonic-gate kmem_alloc(openowner->owner_len, KM_SLEEP); 2096ed57cab9Srg137905 20977c478bd9Sstevel@tonic-gate bcopy(openowner->owner_val, 2098d216dff5SRobert Mastors oo->ro_owner.owner_val, openowner->owner_len); 2099ed57cab9Srg137905 2100d216dff5SRobert Mastors oo->ro_owner.owner_len = openowner->owner_len; 21017c478bd9Sstevel@tonic-gate 2102d216dff5SRobert Mastors oo->ro_need_confirm = TRUE; 21037c478bd9Sstevel@tonic-gate 2104d216dff5SRobert Mastors rfs4_sw_init(&oo->ro_sw); 21057c478bd9Sstevel@tonic-gate 2106d216dff5SRobert Mastors oo->ro_open_seqid = seqid; 2107d216dff5SRobert Mastors bzero(&oo->ro_reply, sizeof (nfs_resop4)); 2108d216dff5SRobert Mastors oo->ro_client = cp; 2109d216dff5SRobert Mastors oo->ro_cr_set = NULL; 2110d216dff5SRobert Mastors 2111d216dff5SRobert Mastors list_create(&oo->ro_statelist, sizeof (rfs4_state_t), 2112d216dff5SRobert Mastors offsetof(rfs4_state_t, rs_node)); 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate /* Insert openowner into client's open owner list */ 2115d216dff5SRobert Mastors rfs4_dbe_lock(cp->rc_dbe); 2116d216dff5SRobert Mastors list_insert_tail(&cp->rc_openownerlist, oo); 2117d216dff5SRobert Mastors rfs4_dbe_unlock(cp->rc_dbe); 21187c478bd9Sstevel@tonic-gate 21197c478bd9Sstevel@tonic-gate return (TRUE); 21207c478bd9Sstevel@tonic-gate } 21217c478bd9Sstevel@tonic-gate 21227c478bd9Sstevel@tonic-gate rfs4_openowner_t * 21237c478bd9Sstevel@tonic-gate rfs4_findopenowner(open_owner4 *openowner, bool_t *create, seqid4 seqid) 21247c478bd9Sstevel@tonic-gate { 2125d216dff5SRobert Mastors rfs4_openowner_t *oo; 21267c478bd9Sstevel@tonic-gate rfs4_openowner_t arg; 21277c478bd9Sstevel@tonic-gate 2128d216dff5SRobert Mastors arg.ro_owner = *openowner; 2129d216dff5SRobert Mastors arg.ro_open_seqid = seqid; 2130d216dff5SRobert Mastors oo = (rfs4_openowner_t *)rfs4_dbsearch(rfs4_openowner_idx, openowner, 21317c478bd9Sstevel@tonic-gate create, &arg, RFS4_DBS_VALID); 21327c478bd9Sstevel@tonic-gate 2133d216dff5SRobert Mastors return (oo); 21347c478bd9Sstevel@tonic-gate } 21357c478bd9Sstevel@tonic-gate 21367c478bd9Sstevel@tonic-gate void 2137d216dff5SRobert Mastors rfs4_update_open_sequence(rfs4_openowner_t *oo) 21387c478bd9Sstevel@tonic-gate { 21397c478bd9Sstevel@tonic-gate 2140d216dff5SRobert Mastors rfs4_dbe_lock(oo->ro_dbe); 21417c478bd9Sstevel@tonic-gate 2142d216dff5SRobert Mastors oo->ro_open_seqid++; 21437c478bd9Sstevel@tonic-gate 2144d216dff5SRobert Mastors rfs4_dbe_unlock(oo->ro_dbe); 21457c478bd9Sstevel@tonic-gate } 21467c478bd9Sstevel@tonic-gate 21477c478bd9Sstevel@tonic-gate void 2148d216dff5SRobert Mastors rfs4_update_open_resp(rfs4_openowner_t *oo, nfs_resop4 *resp, nfs_fh4 *fh) 21497c478bd9Sstevel@tonic-gate { 21507c478bd9Sstevel@tonic-gate 2151d216dff5SRobert Mastors rfs4_dbe_lock(oo->ro_dbe); 21527c478bd9Sstevel@tonic-gate 2153d216dff5SRobert Mastors rfs4_free_reply(&oo->ro_reply); 21547c478bd9Sstevel@tonic-gate 2155d216dff5SRobert Mastors rfs4_copy_reply(&oo->ro_reply, resp); 21567c478bd9Sstevel@tonic-gate 21577c478bd9Sstevel@tonic-gate /* Save the filehandle if provided and free if not used */ 21587c478bd9Sstevel@tonic-gate if (resp->nfs_resop4_u.opopen.status == NFS4_OK && 21597c478bd9Sstevel@tonic-gate fh && fh->nfs_fh4_len) { 2160d216dff5SRobert Mastors if (oo->ro_reply_fh.nfs_fh4_val == NULL) 2161d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_val = 21627c478bd9Sstevel@tonic-gate kmem_alloc(fh->nfs_fh4_len, KM_SLEEP); 2163d216dff5SRobert Mastors nfs_fh4_copy(fh, &oo->ro_reply_fh); 21647c478bd9Sstevel@tonic-gate } else { 2165d216dff5SRobert Mastors if (oo->ro_reply_fh.nfs_fh4_val) { 2166d216dff5SRobert Mastors kmem_free(oo->ro_reply_fh.nfs_fh4_val, 2167d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_len); 2168d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_val = NULL; 2169d216dff5SRobert Mastors oo->ro_reply_fh.nfs_fh4_len = 0; 21707c478bd9Sstevel@tonic-gate } 21717c478bd9Sstevel@tonic-gate } 21727c478bd9Sstevel@tonic-gate 2173d216dff5SRobert Mastors rfs4_dbe_unlock(oo->ro_dbe); 21747c478bd9Sstevel@tonic-gate } 21757c478bd9Sstevel@tonic-gate 21767c478bd9Sstevel@tonic-gate static bool_t 21777c478bd9Sstevel@tonic-gate lockowner_compare(rfs4_entry_t u_entry, void *key) 21787c478bd9Sstevel@tonic-gate { 21797c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; 21807c478bd9Sstevel@tonic-gate lock_owner4 *b = (lock_owner4 *)key; 21817c478bd9Sstevel@tonic-gate 2182d216dff5SRobert Mastors if (lo->rl_owner.clientid != b->clientid) 21837c478bd9Sstevel@tonic-gate return (FALSE); 21847c478bd9Sstevel@tonic-gate 2185d216dff5SRobert Mastors if (lo->rl_owner.owner_len != b->owner_len) 21867c478bd9Sstevel@tonic-gate return (FALSE); 21877c478bd9Sstevel@tonic-gate 2188d216dff5SRobert Mastors return (bcmp(lo->rl_owner.owner_val, b->owner_val, 2189d216dff5SRobert Mastors lo->rl_owner.owner_len) == 0); 21907c478bd9Sstevel@tonic-gate } 21917c478bd9Sstevel@tonic-gate 21927c478bd9Sstevel@tonic-gate void * 21937c478bd9Sstevel@tonic-gate lockowner_mkkey(rfs4_entry_t u_entry) 21947c478bd9Sstevel@tonic-gate { 21957c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; 21967c478bd9Sstevel@tonic-gate 2197d216dff5SRobert Mastors return (&lo->rl_owner); 21987c478bd9Sstevel@tonic-gate } 21997c478bd9Sstevel@tonic-gate 22007c478bd9Sstevel@tonic-gate static uint32_t 22017c478bd9Sstevel@tonic-gate lockowner_hash(void *key) 22027c478bd9Sstevel@tonic-gate { 22037c478bd9Sstevel@tonic-gate int i; 22047c478bd9Sstevel@tonic-gate lock_owner4 *lockowner = key; 22057c478bd9Sstevel@tonic-gate uint_t hash = 0; 22067c478bd9Sstevel@tonic-gate 22077c478bd9Sstevel@tonic-gate for (i = 0; i < lockowner->owner_len; i++) { 22087c478bd9Sstevel@tonic-gate hash <<= 4; 22097c478bd9Sstevel@tonic-gate hash += (uint_t)lockowner->owner_val[i]; 22107c478bd9Sstevel@tonic-gate } 22117c478bd9Sstevel@tonic-gate hash += (uint_t)lockowner->clientid; 22127c478bd9Sstevel@tonic-gate hash |= (lockowner->clientid >> 32); 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gate return (hash); 22157c478bd9Sstevel@tonic-gate } 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gate static uint32_t 22187c478bd9Sstevel@tonic-gate pid_hash(void *key) 22197c478bd9Sstevel@tonic-gate { 22207c478bd9Sstevel@tonic-gate return ((uint32_t)(uintptr_t)key); 22217c478bd9Sstevel@tonic-gate } 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate static void * 22247c478bd9Sstevel@tonic-gate pid_mkkey(rfs4_entry_t u_entry) 22257c478bd9Sstevel@tonic-gate { 22267c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; 22277c478bd9Sstevel@tonic-gate 2228d216dff5SRobert Mastors return ((void *)(uintptr_t)lo->rl_pid); 22297c478bd9Sstevel@tonic-gate } 22307c478bd9Sstevel@tonic-gate 22317c478bd9Sstevel@tonic-gate static bool_t 22327c478bd9Sstevel@tonic-gate pid_compare(rfs4_entry_t u_entry, void *key) 22337c478bd9Sstevel@tonic-gate { 22347c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; 22357c478bd9Sstevel@tonic-gate 2236d216dff5SRobert Mastors return (lo->rl_pid == (pid_t)(uintptr_t)key); 22377c478bd9Sstevel@tonic-gate } 22387c478bd9Sstevel@tonic-gate 22397c478bd9Sstevel@tonic-gate static void 22407c478bd9Sstevel@tonic-gate rfs4_lockowner_destroy(rfs4_entry_t u_entry) 22417c478bd9Sstevel@tonic-gate { 22427c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; 22437c478bd9Sstevel@tonic-gate 22447c478bd9Sstevel@tonic-gate /* Free the lock owner id */ 2245d216dff5SRobert Mastors kmem_free(lo->rl_owner.owner_val, lo->rl_owner.owner_len); 2246d216dff5SRobert Mastors rfs4_client_rele(lo->rl_client); 22477c478bd9Sstevel@tonic-gate } 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate void 22507c478bd9Sstevel@tonic-gate rfs4_lockowner_rele(rfs4_lockowner_t *lo) 22517c478bd9Sstevel@tonic-gate { 2252d216dff5SRobert Mastors rfs4_dbe_rele(lo->rl_dbe); 22537c478bd9Sstevel@tonic-gate } 22547c478bd9Sstevel@tonic-gate 22557c478bd9Sstevel@tonic-gate /* ARGSUSED */ 22567c478bd9Sstevel@tonic-gate static bool_t 22577c478bd9Sstevel@tonic-gate rfs4_lockowner_expiry(rfs4_entry_t u_entry) 22587c478bd9Sstevel@tonic-gate { 22597c478bd9Sstevel@tonic-gate /* 22607c478bd9Sstevel@tonic-gate * Since expiry is called with no other references on 22617c478bd9Sstevel@tonic-gate * this struct, go ahead and have it removed. 22627c478bd9Sstevel@tonic-gate */ 22637c478bd9Sstevel@tonic-gate return (TRUE); 22647c478bd9Sstevel@tonic-gate } 22657c478bd9Sstevel@tonic-gate 22667c478bd9Sstevel@tonic-gate static bool_t 22677c478bd9Sstevel@tonic-gate rfs4_lockowner_create(rfs4_entry_t u_entry, void *arg) 22687c478bd9Sstevel@tonic-gate { 22697c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; 22707c478bd9Sstevel@tonic-gate lock_owner4 *lockowner = (lock_owner4 *)arg; 22717c478bd9Sstevel@tonic-gate rfs4_client_t *cp; 22727c478bd9Sstevel@tonic-gate bool_t create = FALSE; 22737c478bd9Sstevel@tonic-gate 22747c478bd9Sstevel@tonic-gate rw_enter(&rfs4_findclient_lock, RW_READER); 22757c478bd9Sstevel@tonic-gate 22767c478bd9Sstevel@tonic-gate cp = (rfs4_client_t *)rfs4_dbsearch(rfs4_clientid_idx, 22777c478bd9Sstevel@tonic-gate &lockowner->clientid, 22787c478bd9Sstevel@tonic-gate &create, NULL, RFS4_DBS_VALID); 22797c478bd9Sstevel@tonic-gate 22807c478bd9Sstevel@tonic-gate rw_exit(&rfs4_findclient_lock); 22817c478bd9Sstevel@tonic-gate 22827c478bd9Sstevel@tonic-gate if (cp == NULL) 22837c478bd9Sstevel@tonic-gate return (FALSE); 22847c478bd9Sstevel@tonic-gate 22857c478bd9Sstevel@tonic-gate /* Reference client */ 2286d216dff5SRobert Mastors lo->rl_client = cp; 2287d216dff5SRobert Mastors lo->rl_owner.clientid = lockowner->clientid; 2288d216dff5SRobert Mastors lo->rl_owner.owner_val = kmem_alloc(lockowner->owner_len, KM_SLEEP); 2289d216dff5SRobert Mastors bcopy(lockowner->owner_val, lo->rl_owner.owner_val, 2290d216dff5SRobert Mastors lockowner->owner_len); 2291d216dff5SRobert Mastors lo->rl_owner.owner_len = lockowner->owner_len; 2292d216dff5SRobert Mastors lo->rl_pid = rfs4_dbe_getid(lo->rl_dbe); 22937c478bd9Sstevel@tonic-gate 22947c478bd9Sstevel@tonic-gate return (TRUE); 22957c478bd9Sstevel@tonic-gate } 22967c478bd9Sstevel@tonic-gate 22977c478bd9Sstevel@tonic-gate rfs4_lockowner_t * 22987c478bd9Sstevel@tonic-gate rfs4_findlockowner(lock_owner4 *lockowner, bool_t *create) 22997c478bd9Sstevel@tonic-gate { 23007c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo; 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate lo = (rfs4_lockowner_t *)rfs4_dbsearch(rfs4_lockowner_idx, lockowner, 23037c478bd9Sstevel@tonic-gate create, lockowner, RFS4_DBS_VALID); 23047c478bd9Sstevel@tonic-gate 23057c478bd9Sstevel@tonic-gate return (lo); 23067c478bd9Sstevel@tonic-gate } 23077c478bd9Sstevel@tonic-gate 23087c478bd9Sstevel@tonic-gate rfs4_lockowner_t * 23097c478bd9Sstevel@tonic-gate rfs4_findlockowner_by_pid(pid_t pid) 23107c478bd9Sstevel@tonic-gate { 23117c478bd9Sstevel@tonic-gate rfs4_lockowner_t *lo; 23127c478bd9Sstevel@tonic-gate bool_t create = FALSE; 23137c478bd9Sstevel@tonic-gate 23147c478bd9Sstevel@tonic-gate lo = (rfs4_lockowner_t *)rfs4_dbsearch(rfs4_lockowner_pid_idx, 23157c478bd9Sstevel@tonic-gate (void *)(uintptr_t)pid, &create, NULL, RFS4_DBS_VALID); 23167c478bd9Sstevel@tonic-gate 23177c478bd9Sstevel@tonic-gate return (lo); 23187c478bd9Sstevel@tonic-gate } 23197c478bd9Sstevel@tonic-gate 23207c478bd9Sstevel@tonic-gate 23217c478bd9Sstevel@tonic-gate static uint32_t 23227c478bd9Sstevel@tonic-gate file_hash(void *key) 23237c478bd9Sstevel@tonic-gate { 23247c478bd9Sstevel@tonic-gate return (ADDRHASH(key)); 23257c478bd9Sstevel@tonic-gate } 23267c478bd9Sstevel@tonic-gate 23277c478bd9Sstevel@tonic-gate static void * 23287c478bd9Sstevel@tonic-gate file_mkkey(rfs4_entry_t u_entry) 23297c478bd9Sstevel@tonic-gate { 23307c478bd9Sstevel@tonic-gate rfs4_file_t *fp = (rfs4_file_t *)u_entry; 23317c478bd9Sstevel@tonic-gate 2332d216dff5SRobert Mastors return (fp->rf_vp); 23337c478bd9Sstevel@tonic-gate } 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate static bool_t 23367c478bd9Sstevel@tonic-gate file_compare(rfs4_entry_t u_entry, void *key) 23377c478bd9Sstevel@tonic-gate { 23387c478bd9Sstevel@tonic-gate rfs4_file_t *fp = (rfs4_file_t *)u_entry; 23397c478bd9Sstevel@tonic-gate 2340d216dff5SRobert Mastors return (fp->rf_vp == (vnode_t *)key); 23417c478bd9Sstevel@tonic-gate } 23427c478bd9Sstevel@tonic-gate 23437c478bd9Sstevel@tonic-gate static void 23447c478bd9Sstevel@tonic-gate rfs4_file_destroy(rfs4_entry_t u_entry) 23457c478bd9Sstevel@tonic-gate { 23467c478bd9Sstevel@tonic-gate rfs4_file_t *fp = (rfs4_file_t *)u_entry; 23477c478bd9Sstevel@tonic-gate 2348d216dff5SRobert Mastors list_destroy(&fp->rf_delegstatelist); 23491b300de9Sjwahlig 2350d216dff5SRobert Mastors if (fp->rf_filehandle.nfs_fh4_val) 2351d216dff5SRobert Mastors kmem_free(fp->rf_filehandle.nfs_fh4_val, 2352d216dff5SRobert Mastors fp->rf_filehandle.nfs_fh4_len); 2353d216dff5SRobert Mastors cv_destroy(fp->rf_dinfo.rd_recall_cv); 2354d216dff5SRobert Mastors if (fp->rf_vp) { 2355d216dff5SRobert Mastors vnode_t *vp = fp->rf_vp; 2356d216dff5SRobert Mastors 2357d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock); 23581b300de9Sjwahlig (void) vsd_set(vp, nfs4_srv_vkey, NULL); 2359d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock); 23601b300de9Sjwahlig VN_RELE(vp); 2361d216dff5SRobert Mastors fp->rf_vp = NULL; 23627c478bd9Sstevel@tonic-gate } 2363d216dff5SRobert Mastors rw_destroy(&fp->rf_file_rwlock); 23647c478bd9Sstevel@tonic-gate } 23657c478bd9Sstevel@tonic-gate 23667c478bd9Sstevel@tonic-gate /* 23677c478bd9Sstevel@tonic-gate * Used to unlock the underlying dbe struct only 23687c478bd9Sstevel@tonic-gate */ 23697c478bd9Sstevel@tonic-gate void 23707c478bd9Sstevel@tonic-gate rfs4_file_rele(rfs4_file_t *fp) 23717c478bd9Sstevel@tonic-gate { 2372d216dff5SRobert Mastors rfs4_dbe_rele(fp->rf_dbe); 23737c478bd9Sstevel@tonic-gate } 23747c478bd9Sstevel@tonic-gate 23757c478bd9Sstevel@tonic-gate typedef struct { 23767c478bd9Sstevel@tonic-gate vnode_t *vp; 23777c478bd9Sstevel@tonic-gate nfs_fh4 *fh; 23787c478bd9Sstevel@tonic-gate } rfs4_fcreate_arg; 23797c478bd9Sstevel@tonic-gate 23807c478bd9Sstevel@tonic-gate static bool_t 23817c478bd9Sstevel@tonic-gate rfs4_file_create(rfs4_entry_t u_entry, void *arg) 23827c478bd9Sstevel@tonic-gate { 23837c478bd9Sstevel@tonic-gate rfs4_file_t *fp = (rfs4_file_t *)u_entry; 23847c478bd9Sstevel@tonic-gate rfs4_fcreate_arg *ap = (rfs4_fcreate_arg *)arg; 23857c478bd9Sstevel@tonic-gate vnode_t *vp = ap->vp; 23867c478bd9Sstevel@tonic-gate nfs_fh4 *fh = ap->fh; 23877c478bd9Sstevel@tonic-gate 23887c478bd9Sstevel@tonic-gate VN_HOLD(vp); 23897c478bd9Sstevel@tonic-gate 2390d216dff5SRobert Mastors fp->rf_filehandle.nfs_fh4_len = 0; 2391d216dff5SRobert Mastors fp->rf_filehandle.nfs_fh4_val = NULL; 23927c478bd9Sstevel@tonic-gate ASSERT(fh && fh->nfs_fh4_len); 23937c478bd9Sstevel@tonic-gate if (fh && fh->nfs_fh4_len) { 2394d216dff5SRobert Mastors fp->rf_filehandle.nfs_fh4_val = 23957c478bd9Sstevel@tonic-gate kmem_alloc(fh->nfs_fh4_len, KM_SLEEP); 2396d216dff5SRobert Mastors nfs_fh4_copy(fh, &fp->rf_filehandle); 23977c478bd9Sstevel@tonic-gate } 2398d216dff5SRobert Mastors fp->rf_vp = vp; 23997c478bd9Sstevel@tonic-gate 2400d216dff5SRobert Mastors list_create(&fp->rf_delegstatelist, sizeof (rfs4_deleg_state_t), 2401d216dff5SRobert Mastors offsetof(rfs4_deleg_state_t, rds_node)); 24027c478bd9Sstevel@tonic-gate 2403d216dff5SRobert Mastors fp->rf_share_deny = fp->rf_share_access = fp->rf_access_read = 0; 2404d216dff5SRobert Mastors fp->rf_access_write = fp->rf_deny_read = fp->rf_deny_write = 0; 24057c478bd9Sstevel@tonic-gate 2406d216dff5SRobert Mastors mutex_init(fp->rf_dinfo.rd_recall_lock, NULL, MUTEX_DEFAULT, NULL); 2407d216dff5SRobert Mastors cv_init(fp->rf_dinfo.rd_recall_cv, NULL, CV_DEFAULT, NULL); 24087c478bd9Sstevel@tonic-gate 2409d216dff5SRobert Mastors fp->rf_dinfo.rd_dtype = OPEN_DELEGATE_NONE; 24107c478bd9Sstevel@tonic-gate 2411d216dff5SRobert Mastors rw_init(&fp->rf_file_rwlock, NULL, RW_DEFAULT, NULL); 24127c478bd9Sstevel@tonic-gate 2413d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock); 2414d216dff5SRobert Mastors VERIFY(vsd_set(vp, nfs4_srv_vkey, (void *)fp) == 0); 2415d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock); 24161b300de9Sjwahlig 24177c478bd9Sstevel@tonic-gate return (TRUE); 24187c478bd9Sstevel@tonic-gate } 24197c478bd9Sstevel@tonic-gate 24207c478bd9Sstevel@tonic-gate rfs4_file_t * 24217c478bd9Sstevel@tonic-gate rfs4_findfile(vnode_t *vp, nfs_fh4 *fh, bool_t *create) 24227c478bd9Sstevel@tonic-gate { 24237c478bd9Sstevel@tonic-gate rfs4_file_t *fp; 24247c478bd9Sstevel@tonic-gate rfs4_fcreate_arg arg; 24257c478bd9Sstevel@tonic-gate 24267c478bd9Sstevel@tonic-gate arg.vp = vp; 24277c478bd9Sstevel@tonic-gate arg.fh = fh; 24287c478bd9Sstevel@tonic-gate 24291b300de9Sjwahlig if (*create == TRUE) 24307c478bd9Sstevel@tonic-gate fp = (rfs4_file_t *)rfs4_dbsearch(rfs4_file_idx, vp, create, 24317c478bd9Sstevel@tonic-gate &arg, RFS4_DBS_VALID); 24321b300de9Sjwahlig else { 2433d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock); 24341b300de9Sjwahlig fp = (rfs4_file_t *)vsd_get(vp, nfs4_srv_vkey); 24351b300de9Sjwahlig if (fp) { 2436d216dff5SRobert Mastors rfs4_dbe_lock(fp->rf_dbe); 2437d216dff5SRobert Mastors if (rfs4_dbe_is_invalid(fp->rf_dbe) || 2438d216dff5SRobert Mastors (rfs4_dbe_refcnt(fp->rf_dbe) == 0)) { 2439d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe); 24401b300de9Sjwahlig fp = NULL; 24411b300de9Sjwahlig } else { 2442d216dff5SRobert Mastors rfs4_dbe_hold(fp->rf_dbe); 2443d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe); 24441b300de9Sjwahlig } 24451b300de9Sjwahlig } 2446d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock); 24471b300de9Sjwahlig } 24487c478bd9Sstevel@tonic-gate return (fp); 24497c478bd9Sstevel@tonic-gate } 24507c478bd9Sstevel@tonic-gate 24517c478bd9Sstevel@tonic-gate /* 24527c478bd9Sstevel@tonic-gate * Find a file in the db and once it is located, take the rw lock. 24537c478bd9Sstevel@tonic-gate * Need to check the vnode pointer and if it does not exist (it was 24547c478bd9Sstevel@tonic-gate * removed between the db location and check) redo the find. This 24557c478bd9Sstevel@tonic-gate * assumes that a file struct that has a NULL vnode pointer is marked 24567c478bd9Sstevel@tonic-gate * at 'invalid' and will not be found in the db the second time 24577c478bd9Sstevel@tonic-gate * around. 24587c478bd9Sstevel@tonic-gate */ 24597c478bd9Sstevel@tonic-gate rfs4_file_t * 24607c478bd9Sstevel@tonic-gate rfs4_findfile_withlock(vnode_t *vp, nfs_fh4 *fh, bool_t *create) 24617c478bd9Sstevel@tonic-gate { 24627c478bd9Sstevel@tonic-gate rfs4_file_t *fp; 24637c478bd9Sstevel@tonic-gate rfs4_fcreate_arg arg; 24647c478bd9Sstevel@tonic-gate bool_t screate = *create; 24657c478bd9Sstevel@tonic-gate 24661b300de9Sjwahlig if (screate == FALSE) { 2467d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock); 24681b300de9Sjwahlig fp = (rfs4_file_t *)vsd_get(vp, nfs4_srv_vkey); 24691b300de9Sjwahlig if (fp) { 2470d216dff5SRobert Mastors rfs4_dbe_lock(fp->rf_dbe); 2471d216dff5SRobert Mastors if (rfs4_dbe_is_invalid(fp->rf_dbe) || 2472d216dff5SRobert Mastors (rfs4_dbe_refcnt(fp->rf_dbe) == 0)) { 2473d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe); 2474d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock); 24751b300de9Sjwahlig fp = NULL; 24761b300de9Sjwahlig } else { 2477d216dff5SRobert Mastors rfs4_dbe_hold(fp->rf_dbe); 2478d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe); 2479d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock); 2480d216dff5SRobert Mastors rw_enter(&fp->rf_file_rwlock, RW_WRITER); 2481d216dff5SRobert Mastors if (fp->rf_vp == NULL) { 2482d216dff5SRobert Mastors rw_exit(&fp->rf_file_rwlock); 2483a08f57bcSJames Wahlig rfs4_file_rele(fp); 2484a08f57bcSJames Wahlig fp = NULL; 2485a08f57bcSJames Wahlig } 24861b300de9Sjwahlig } 2487d216dff5SRobert Mastors } else { 2488d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock); 24891b300de9Sjwahlig } 24901b300de9Sjwahlig } else { 24917c478bd9Sstevel@tonic-gate retry: 24927c478bd9Sstevel@tonic-gate arg.vp = vp; 24937c478bd9Sstevel@tonic-gate arg.fh = fh; 24947c478bd9Sstevel@tonic-gate 24957c478bd9Sstevel@tonic-gate fp = (rfs4_file_t *)rfs4_dbsearch(rfs4_file_idx, vp, create, 24967c478bd9Sstevel@tonic-gate &arg, RFS4_DBS_VALID); 24977c478bd9Sstevel@tonic-gate if (fp != NULL) { 2498d216dff5SRobert Mastors rw_enter(&fp->rf_file_rwlock, RW_WRITER); 2499d216dff5SRobert Mastors if (fp->rf_vp == NULL) { 2500d216dff5SRobert Mastors rw_exit(&fp->rf_file_rwlock); 25017c478bd9Sstevel@tonic-gate rfs4_file_rele(fp); 25027c478bd9Sstevel@tonic-gate *create = screate; 25037c478bd9Sstevel@tonic-gate goto retry; 25047c478bd9Sstevel@tonic-gate } 25057c478bd9Sstevel@tonic-gate } 25061b300de9Sjwahlig } 25077c478bd9Sstevel@tonic-gate 25087c478bd9Sstevel@tonic-gate return (fp); 25097c478bd9Sstevel@tonic-gate } 25107c478bd9Sstevel@tonic-gate 25117c478bd9Sstevel@tonic-gate static uint32_t 25127c478bd9Sstevel@tonic-gate lo_state_hash(void *key) 25137c478bd9Sstevel@tonic-gate { 25147c478bd9Sstevel@tonic-gate stateid_t *id = key; 25157c478bd9Sstevel@tonic-gate 25167c478bd9Sstevel@tonic-gate return (id->bits.ident+id->bits.pid); 25177c478bd9Sstevel@tonic-gate } 25187c478bd9Sstevel@tonic-gate 25197c478bd9Sstevel@tonic-gate static bool_t 25207c478bd9Sstevel@tonic-gate lo_state_compare(rfs4_entry_t u_entry, void *key) 25217c478bd9Sstevel@tonic-gate { 2522d216dff5SRobert Mastors rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; 25237c478bd9Sstevel@tonic-gate stateid_t *id = key; 25247c478bd9Sstevel@tonic-gate bool_t rc; 25257c478bd9Sstevel@tonic-gate 2526d216dff5SRobert Mastors rc = (lsp->rls_lockid.bits.boottime == id->bits.boottime && 2527d216dff5SRobert Mastors lsp->rls_lockid.bits.type == id->bits.type && 2528d216dff5SRobert Mastors lsp->rls_lockid.bits.ident == id->bits.ident && 2529d216dff5SRobert Mastors lsp->rls_lockid.bits.pid == id->bits.pid); 25307c478bd9Sstevel@tonic-gate 25317c478bd9Sstevel@tonic-gate return (rc); 25327c478bd9Sstevel@tonic-gate } 25337c478bd9Sstevel@tonic-gate 25347c478bd9Sstevel@tonic-gate static void * 25357c478bd9Sstevel@tonic-gate lo_state_mkkey(rfs4_entry_t u_entry) 25367c478bd9Sstevel@tonic-gate { 25377c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; 25387c478bd9Sstevel@tonic-gate 2539d216dff5SRobert Mastors return (&lsp->rls_lockid); 25407c478bd9Sstevel@tonic-gate } 25417c478bd9Sstevel@tonic-gate 25427c478bd9Sstevel@tonic-gate static bool_t 25437c478bd9Sstevel@tonic-gate rfs4_lo_state_expiry(rfs4_entry_t u_entry) 25447c478bd9Sstevel@tonic-gate { 25457c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; 25467c478bd9Sstevel@tonic-gate 2547d216dff5SRobert Mastors if (rfs4_dbe_is_invalid(lsp->rls_dbe)) 25487c478bd9Sstevel@tonic-gate return (TRUE); 2549d216dff5SRobert Mastors if (lsp->rls_state->rs_closed) 25507c478bd9Sstevel@tonic-gate return (TRUE); 2551d216dff5SRobert Mastors return ((gethrestime_sec() - 2552d216dff5SRobert Mastors lsp->rls_state->rs_owner->ro_client->rc_last_access 25537c478bd9Sstevel@tonic-gate > rfs4_lease_time)); 25547c478bd9Sstevel@tonic-gate } 25557c478bd9Sstevel@tonic-gate 25567c478bd9Sstevel@tonic-gate static void 25577c478bd9Sstevel@tonic-gate rfs4_lo_state_destroy(rfs4_entry_t u_entry) 25587c478bd9Sstevel@tonic-gate { 25597c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; 25607c478bd9Sstevel@tonic-gate 2561d216dff5SRobert Mastors rfs4_dbe_lock(lsp->rls_state->rs_dbe); 2562d216dff5SRobert Mastors list_remove(&lsp->rls_state->rs_lostatelist, lsp); 2563d216dff5SRobert Mastors rfs4_dbe_unlock(lsp->rls_state->rs_dbe); 2564d216dff5SRobert Mastors 2565d216dff5SRobert Mastors rfs4_sw_destroy(&lsp->rls_sw); 25667c478bd9Sstevel@tonic-gate 25677c478bd9Sstevel@tonic-gate /* Make sure to release the file locks */ 2568d216dff5SRobert Mastors if (lsp->rls_locks_cleaned == FALSE) { 2569d216dff5SRobert Mastors lsp->rls_locks_cleaned = TRUE; 2570d216dff5SRobert Mastors if (lsp->rls_locker->rl_client->rc_sysidt != LM_NOSYSID) { 25717c478bd9Sstevel@tonic-gate /* Is the PxFS kernel module loaded? */ 25727c478bd9Sstevel@tonic-gate if (lm_remove_file_locks != NULL) { 25737c478bd9Sstevel@tonic-gate int new_sysid; 25747c478bd9Sstevel@tonic-gate 25757c478bd9Sstevel@tonic-gate /* Encode the cluster nodeid in new sysid */ 2576d216dff5SRobert Mastors new_sysid = 2577d216dff5SRobert Mastors lsp->rls_locker->rl_client->rc_sysidt; 25787c478bd9Sstevel@tonic-gate lm_set_nlmid_flk(&new_sysid); 25797c478bd9Sstevel@tonic-gate 25807c478bd9Sstevel@tonic-gate /* 25817c478bd9Sstevel@tonic-gate * This PxFS routine removes file locks for a 25827c478bd9Sstevel@tonic-gate * client over all nodes of a cluster. 25837c478bd9Sstevel@tonic-gate */ 2584ed57cab9Srg137905 DTRACE_PROBE1(nfss_i_clust_rm_lck, 2585ed57cab9Srg137905 int, new_sysid); 25867c478bd9Sstevel@tonic-gate (*lm_remove_file_locks)(new_sysid); 25877c478bd9Sstevel@tonic-gate } else { 2588d216dff5SRobert Mastors (void) cleanlocks( 2589d216dff5SRobert Mastors lsp->rls_state->rs_finfo->rf_vp, 2590d216dff5SRobert Mastors lsp->rls_locker->rl_pid, 2591d216dff5SRobert Mastors lsp->rls_locker->rl_client->rc_sysidt); 25927c478bd9Sstevel@tonic-gate } 25937c478bd9Sstevel@tonic-gate } 25947c478bd9Sstevel@tonic-gate } 25957c478bd9Sstevel@tonic-gate 25967c478bd9Sstevel@tonic-gate /* Free the last reply for this state */ 2597d216dff5SRobert Mastors rfs4_free_reply(&lsp->rls_reply); 25987c478bd9Sstevel@tonic-gate 2599d216dff5SRobert Mastors rfs4_lockowner_rele(lsp->rls_locker); 2600d216dff5SRobert Mastors lsp->rls_locker = NULL; 26017c478bd9Sstevel@tonic-gate 2602d216dff5SRobert Mastors rfs4_state_rele_nounlock(lsp->rls_state); 2603d216dff5SRobert Mastors lsp->rls_state = NULL; 26047c478bd9Sstevel@tonic-gate } 26057c478bd9Sstevel@tonic-gate 26067c478bd9Sstevel@tonic-gate static bool_t 26077c478bd9Sstevel@tonic-gate rfs4_lo_state_create(rfs4_entry_t u_entry, void *arg) 26087c478bd9Sstevel@tonic-gate { 26097c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; 26107c478bd9Sstevel@tonic-gate rfs4_lo_state_t *argp = (rfs4_lo_state_t *)arg; 2611d216dff5SRobert Mastors rfs4_lockowner_t *lo = argp->rls_locker; 2612d216dff5SRobert Mastors rfs4_state_t *sp = argp->rls_state; 26137c478bd9Sstevel@tonic-gate 2614d216dff5SRobert Mastors lsp->rls_state = sp; 26157c478bd9Sstevel@tonic-gate 2616d216dff5SRobert Mastors lsp->rls_lockid = sp->rs_stateid; 2617d216dff5SRobert Mastors lsp->rls_lockid.bits.type = LOCKID; 2618d216dff5SRobert Mastors lsp->rls_lockid.bits.chgseq = 0; 2619d216dff5SRobert Mastors lsp->rls_lockid.bits.pid = lo->rl_pid; 26207c478bd9Sstevel@tonic-gate 2621d216dff5SRobert Mastors lsp->rls_locks_cleaned = FALSE; 2622d216dff5SRobert Mastors lsp->rls_lock_completed = FALSE; 26237c478bd9Sstevel@tonic-gate 2624d216dff5SRobert Mastors rfs4_sw_init(&lsp->rls_sw); 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate /* Attached the supplied lock owner */ 2627d216dff5SRobert Mastors rfs4_dbe_hold(lo->rl_dbe); 2628d216dff5SRobert Mastors lsp->rls_locker = lo; 26297c478bd9Sstevel@tonic-gate 2630d216dff5SRobert Mastors rfs4_dbe_lock(sp->rs_dbe); 2631d216dff5SRobert Mastors list_insert_tail(&sp->rs_lostatelist, lsp); 2632d216dff5SRobert Mastors rfs4_dbe_hold(sp->rs_dbe); 2633d216dff5SRobert Mastors rfs4_dbe_unlock(sp->rs_dbe); 26347c478bd9Sstevel@tonic-gate 26357c478bd9Sstevel@tonic-gate return (TRUE); 26367c478bd9Sstevel@tonic-gate } 26377c478bd9Sstevel@tonic-gate 26387c478bd9Sstevel@tonic-gate void 26397c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(rfs4_lo_state_t *lsp, bool_t unlock_fp) 26407c478bd9Sstevel@tonic-gate { 26417c478bd9Sstevel@tonic-gate if (unlock_fp == TRUE) 2642d216dff5SRobert Mastors rw_exit(&lsp->rls_state->rs_finfo->rf_file_rwlock); 2643d216dff5SRobert Mastors rfs4_dbe_rele(lsp->rls_dbe); 26447c478bd9Sstevel@tonic-gate } 26457c478bd9Sstevel@tonic-gate 26467c478bd9Sstevel@tonic-gate static rfs4_lo_state_t * 26477c478bd9Sstevel@tonic-gate rfs4_findlo_state(stateid_t *id, bool_t lock_fp) 26487c478bd9Sstevel@tonic-gate { 26497c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp; 26507c478bd9Sstevel@tonic-gate bool_t create = FALSE; 26517c478bd9Sstevel@tonic-gate 26527c478bd9Sstevel@tonic-gate lsp = (rfs4_lo_state_t *)rfs4_dbsearch(rfs4_lo_state_idx, id, 26537c478bd9Sstevel@tonic-gate &create, NULL, RFS4_DBS_VALID); 26547c478bd9Sstevel@tonic-gate if (lock_fp == TRUE && lsp != NULL) 2655d216dff5SRobert Mastors rw_enter(&lsp->rls_state->rs_finfo->rf_file_rwlock, RW_READER); 26567c478bd9Sstevel@tonic-gate 26577c478bd9Sstevel@tonic-gate return (lsp); 26587c478bd9Sstevel@tonic-gate } 26597c478bd9Sstevel@tonic-gate 26607c478bd9Sstevel@tonic-gate 26617c478bd9Sstevel@tonic-gate static uint32_t 26627c478bd9Sstevel@tonic-gate lo_state_lo_hash(void *key) 26637c478bd9Sstevel@tonic-gate { 2664d216dff5SRobert Mastors rfs4_lo_state_t *lsp = key; 26657c478bd9Sstevel@tonic-gate 2666d216dff5SRobert Mastors return (ADDRHASH(lsp->rls_locker) ^ ADDRHASH(lsp->rls_state)); 26677c478bd9Sstevel@tonic-gate } 26687c478bd9Sstevel@tonic-gate 26697c478bd9Sstevel@tonic-gate static bool_t 26707c478bd9Sstevel@tonic-gate lo_state_lo_compare(rfs4_entry_t u_entry, void *key) 26717c478bd9Sstevel@tonic-gate { 2672d216dff5SRobert Mastors rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; 26737c478bd9Sstevel@tonic-gate rfs4_lo_state_t *keyp = key; 26747c478bd9Sstevel@tonic-gate 2675d216dff5SRobert Mastors return (keyp->rls_locker == lsp->rls_locker && 2676d216dff5SRobert Mastors keyp->rls_state == lsp->rls_state); 26777c478bd9Sstevel@tonic-gate } 26787c478bd9Sstevel@tonic-gate 26797c478bd9Sstevel@tonic-gate static void * 26807c478bd9Sstevel@tonic-gate lo_state_lo_mkkey(rfs4_entry_t u_entry) 26817c478bd9Sstevel@tonic-gate { 26827c478bd9Sstevel@tonic-gate return (u_entry); 26837c478bd9Sstevel@tonic-gate } 26847c478bd9Sstevel@tonic-gate 26857c478bd9Sstevel@tonic-gate rfs4_lo_state_t * 2686d216dff5SRobert Mastors rfs4_findlo_state_by_owner(rfs4_lockowner_t *lo, rfs4_state_t *sp, 2687d216dff5SRobert Mastors bool_t *create) 26887c478bd9Sstevel@tonic-gate { 26897c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp; 26907c478bd9Sstevel@tonic-gate rfs4_lo_state_t arg; 26917c478bd9Sstevel@tonic-gate 2692d216dff5SRobert Mastors arg.rls_locker = lo; 2693d216dff5SRobert Mastors arg.rls_state = sp; 26947c478bd9Sstevel@tonic-gate 26957c478bd9Sstevel@tonic-gate lsp = (rfs4_lo_state_t *)rfs4_dbsearch(rfs4_lo_state_owner_idx, &arg, 26967c478bd9Sstevel@tonic-gate create, &arg, RFS4_DBS_VALID); 26977c478bd9Sstevel@tonic-gate 26987c478bd9Sstevel@tonic-gate return (lsp); 26997c478bd9Sstevel@tonic-gate } 27007c478bd9Sstevel@tonic-gate 27017c478bd9Sstevel@tonic-gate static stateid_t 27027c478bd9Sstevel@tonic-gate get_stateid(id_t eid) 27037c478bd9Sstevel@tonic-gate { 27047c478bd9Sstevel@tonic-gate stateid_t id; 27057c478bd9Sstevel@tonic-gate 27067c478bd9Sstevel@tonic-gate id.bits.boottime = rfs4_start_time; 27077c478bd9Sstevel@tonic-gate id.bits.ident = eid; 27087c478bd9Sstevel@tonic-gate id.bits.chgseq = 0; 27097c478bd9Sstevel@tonic-gate id.bits.type = 0; 27107c478bd9Sstevel@tonic-gate id.bits.pid = 0; 27117c478bd9Sstevel@tonic-gate 27127c478bd9Sstevel@tonic-gate /* 27137c478bd9Sstevel@tonic-gate * If we are booted as a cluster node, embed our nodeid. 27147c478bd9Sstevel@tonic-gate * We've already done sanity checks in rfs4_client_create() so no 27157c478bd9Sstevel@tonic-gate * need to repeat them here. 27167c478bd9Sstevel@tonic-gate */ 27177c478bd9Sstevel@tonic-gate id.bits.clnodeid = (cluster_bootflags & CLUSTER_BOOTED) ? 27187c478bd9Sstevel@tonic-gate clconf_get_nodeid() : 0; 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate return (id); 27217c478bd9Sstevel@tonic-gate } 27227c478bd9Sstevel@tonic-gate 27237c478bd9Sstevel@tonic-gate /* 27247c478bd9Sstevel@tonic-gate * For use only when booted as a cluster node. 27257c478bd9Sstevel@tonic-gate * Returns TRUE if the embedded nodeid indicates that this stateid was 27267c478bd9Sstevel@tonic-gate * generated on another node. 27277c478bd9Sstevel@tonic-gate */ 27287c478bd9Sstevel@tonic-gate static int 27297c478bd9Sstevel@tonic-gate foreign_stateid(stateid_t *id) 27307c478bd9Sstevel@tonic-gate { 27317c478bd9Sstevel@tonic-gate ASSERT(cluster_bootflags & CLUSTER_BOOTED); 27327c478bd9Sstevel@tonic-gate return (id->bits.clnodeid != (uint32_t)clconf_get_nodeid()); 27337c478bd9Sstevel@tonic-gate } 27347c478bd9Sstevel@tonic-gate 27357c478bd9Sstevel@tonic-gate /* 27367c478bd9Sstevel@tonic-gate * For use only when booted as a cluster node. 27377c478bd9Sstevel@tonic-gate * Returns TRUE if the embedded nodeid indicates that this clientid was 27387c478bd9Sstevel@tonic-gate * generated on another node. 27397c478bd9Sstevel@tonic-gate */ 27407c478bd9Sstevel@tonic-gate static int 27417c478bd9Sstevel@tonic-gate foreign_clientid(cid *cidp) 27427c478bd9Sstevel@tonic-gate { 27437c478bd9Sstevel@tonic-gate ASSERT(cluster_bootflags & CLUSTER_BOOTED); 27447c478bd9Sstevel@tonic-gate return (cidp->impl_id.c_id >> CLUSTER_NODEID_SHIFT != 27457c478bd9Sstevel@tonic-gate (uint32_t)clconf_get_nodeid()); 27467c478bd9Sstevel@tonic-gate } 27477c478bd9Sstevel@tonic-gate 27487c478bd9Sstevel@tonic-gate /* 27497c478bd9Sstevel@tonic-gate * For use only when booted as a cluster node. 27507c478bd9Sstevel@tonic-gate * Embed our cluster nodeid into the clientid. 27517c478bd9Sstevel@tonic-gate */ 27527c478bd9Sstevel@tonic-gate static void 27537c478bd9Sstevel@tonic-gate embed_nodeid(cid *cidp) 27547c478bd9Sstevel@tonic-gate { 27557c478bd9Sstevel@tonic-gate int clnodeid; 27567c478bd9Sstevel@tonic-gate /* 27577c478bd9Sstevel@tonic-gate * Currently, our state tables are small enough that their 27587c478bd9Sstevel@tonic-gate * ids will leave enough bits free for the nodeid. If the 27597c478bd9Sstevel@tonic-gate * tables become larger, we mustn't overwrite the id. 27607c478bd9Sstevel@tonic-gate * Equally, we only have room for so many bits of nodeid, so 27617c478bd9Sstevel@tonic-gate * must check that too. 27627c478bd9Sstevel@tonic-gate */ 27637c478bd9Sstevel@tonic-gate ASSERT(cluster_bootflags & CLUSTER_BOOTED); 27647c478bd9Sstevel@tonic-gate ASSERT(cidp->impl_id.c_id >> CLUSTER_NODEID_SHIFT == 0); 27657c478bd9Sstevel@tonic-gate clnodeid = clconf_get_nodeid(); 27667c478bd9Sstevel@tonic-gate ASSERT(clnodeid <= CLUSTER_MAX_NODEID); 27677c478bd9Sstevel@tonic-gate ASSERT(clnodeid != NODEID_UNKNOWN); 27687c478bd9Sstevel@tonic-gate cidp->impl_id.c_id |= (clnodeid << CLUSTER_NODEID_SHIFT); 27697c478bd9Sstevel@tonic-gate } 27707c478bd9Sstevel@tonic-gate 27717c478bd9Sstevel@tonic-gate static uint32_t 27727c478bd9Sstevel@tonic-gate state_hash(void *key) 27737c478bd9Sstevel@tonic-gate { 27747c478bd9Sstevel@tonic-gate stateid_t *ip = (stateid_t *)key; 27757c478bd9Sstevel@tonic-gate 27767c478bd9Sstevel@tonic-gate return (ip->bits.ident); 27777c478bd9Sstevel@tonic-gate } 27787c478bd9Sstevel@tonic-gate 27797c478bd9Sstevel@tonic-gate static bool_t 27807c478bd9Sstevel@tonic-gate state_compare(rfs4_entry_t u_entry, void *key) 27817c478bd9Sstevel@tonic-gate { 27827c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry; 27837c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)key; 27847c478bd9Sstevel@tonic-gate bool_t rc; 27857c478bd9Sstevel@tonic-gate 2786d216dff5SRobert Mastors rc = (sp->rs_stateid.bits.boottime == id->bits.boottime && 2787d216dff5SRobert Mastors sp->rs_stateid.bits.ident == id->bits.ident); 27887c478bd9Sstevel@tonic-gate 27897c478bd9Sstevel@tonic-gate return (rc); 27907c478bd9Sstevel@tonic-gate } 27917c478bd9Sstevel@tonic-gate 27927c478bd9Sstevel@tonic-gate static void * 27937c478bd9Sstevel@tonic-gate state_mkkey(rfs4_entry_t u_entry) 27947c478bd9Sstevel@tonic-gate { 27957c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry; 27967c478bd9Sstevel@tonic-gate 2797d216dff5SRobert Mastors return (&sp->rs_stateid); 27987c478bd9Sstevel@tonic-gate } 27997c478bd9Sstevel@tonic-gate 28007c478bd9Sstevel@tonic-gate static void 28017c478bd9Sstevel@tonic-gate rfs4_state_destroy(rfs4_entry_t u_entry) 28027c478bd9Sstevel@tonic-gate { 28037c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry; 28047c478bd9Sstevel@tonic-gate 2805d216dff5SRobert Mastors /* remove from openowner list */ 2806d216dff5SRobert Mastors rfs4_dbe_lock(sp->rs_owner->ro_dbe); 2807d216dff5SRobert Mastors list_remove(&sp->rs_owner->ro_statelist, sp); 2808d216dff5SRobert Mastors rfs4_dbe_unlock(sp->rs_owner->ro_dbe); 2809d216dff5SRobert Mastors 2810d216dff5SRobert Mastors list_destroy(&sp->rs_lostatelist); 28117c478bd9Sstevel@tonic-gate 28127c478bd9Sstevel@tonic-gate /* release any share locks for this stateid if it's still open */ 2813d216dff5SRobert Mastors if (!sp->rs_closed) { 2814d216dff5SRobert Mastors rfs4_dbe_lock(sp->rs_dbe); 2815d216dff5SRobert Mastors (void) rfs4_unshare(sp); 2816d216dff5SRobert Mastors rfs4_dbe_unlock(sp->rs_dbe); 2817d216dff5SRobert Mastors } 28187c478bd9Sstevel@tonic-gate 28197c478bd9Sstevel@tonic-gate /* Were done with the file */ 2820d216dff5SRobert Mastors rfs4_file_rele(sp->rs_finfo); 2821d216dff5SRobert Mastors sp->rs_finfo = NULL; 28227c478bd9Sstevel@tonic-gate 28237c478bd9Sstevel@tonic-gate /* And now with the openowner */ 2824d216dff5SRobert Mastors rfs4_openowner_rele(sp->rs_owner); 2825d216dff5SRobert Mastors sp->rs_owner = NULL; 28267c478bd9Sstevel@tonic-gate } 28277c478bd9Sstevel@tonic-gate 28287c478bd9Sstevel@tonic-gate static void 28297c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(rfs4_state_t *sp) 28307c478bd9Sstevel@tonic-gate { 2831d216dff5SRobert Mastors rfs4_dbe_rele(sp->rs_dbe); 28327c478bd9Sstevel@tonic-gate } 28337c478bd9Sstevel@tonic-gate 28347c478bd9Sstevel@tonic-gate void 28357c478bd9Sstevel@tonic-gate rfs4_state_rele(rfs4_state_t *sp) 28367c478bd9Sstevel@tonic-gate { 2837d216dff5SRobert Mastors rw_exit(&sp->rs_finfo->rf_file_rwlock); 2838d216dff5SRobert Mastors rfs4_dbe_rele(sp->rs_dbe); 28397c478bd9Sstevel@tonic-gate } 28407c478bd9Sstevel@tonic-gate 28417c478bd9Sstevel@tonic-gate static uint32_t 28427c478bd9Sstevel@tonic-gate deleg_hash(void *key) 28437c478bd9Sstevel@tonic-gate { 28447c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)key; 28457c478bd9Sstevel@tonic-gate 2846d216dff5SRobert Mastors return (ADDRHASH(dsp->rds_client) ^ ADDRHASH(dsp->rds_finfo)); 28477c478bd9Sstevel@tonic-gate } 28487c478bd9Sstevel@tonic-gate 28497c478bd9Sstevel@tonic-gate static bool_t 28507c478bd9Sstevel@tonic-gate deleg_compare(rfs4_entry_t u_entry, void *key) 28517c478bd9Sstevel@tonic-gate { 28527c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; 28537c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *kdsp = (rfs4_deleg_state_t *)key; 28547c478bd9Sstevel@tonic-gate 2855d216dff5SRobert Mastors return (dsp->rds_client == kdsp->rds_client && 2856d216dff5SRobert Mastors dsp->rds_finfo == kdsp->rds_finfo); 28577c478bd9Sstevel@tonic-gate } 28587c478bd9Sstevel@tonic-gate 28597c478bd9Sstevel@tonic-gate static void * 28607c478bd9Sstevel@tonic-gate deleg_mkkey(rfs4_entry_t u_entry) 28617c478bd9Sstevel@tonic-gate { 28627c478bd9Sstevel@tonic-gate return (u_entry); 28637c478bd9Sstevel@tonic-gate } 28647c478bd9Sstevel@tonic-gate 28657c478bd9Sstevel@tonic-gate static uint32_t 28667c478bd9Sstevel@tonic-gate deleg_state_hash(void *key) 28677c478bd9Sstevel@tonic-gate { 28687c478bd9Sstevel@tonic-gate stateid_t *ip = (stateid_t *)key; 28697c478bd9Sstevel@tonic-gate 28707c478bd9Sstevel@tonic-gate return (ip->bits.ident); 28717c478bd9Sstevel@tonic-gate } 28727c478bd9Sstevel@tonic-gate 28737c478bd9Sstevel@tonic-gate static bool_t 28747c478bd9Sstevel@tonic-gate deleg_state_compare(rfs4_entry_t u_entry, void *key) 28757c478bd9Sstevel@tonic-gate { 28767c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; 28777c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)key; 28787c478bd9Sstevel@tonic-gate bool_t rc; 28797c478bd9Sstevel@tonic-gate 28807c478bd9Sstevel@tonic-gate if (id->bits.type != DELEGID) 28817c478bd9Sstevel@tonic-gate return (FALSE); 28827c478bd9Sstevel@tonic-gate 2883d216dff5SRobert Mastors rc = (dsp->rds_delegid.bits.boottime == id->bits.boottime && 2884d216dff5SRobert Mastors dsp->rds_delegid.bits.ident == id->bits.ident); 28857c478bd9Sstevel@tonic-gate 28867c478bd9Sstevel@tonic-gate return (rc); 28877c478bd9Sstevel@tonic-gate } 28887c478bd9Sstevel@tonic-gate 28897c478bd9Sstevel@tonic-gate static void * 28907c478bd9Sstevel@tonic-gate deleg_state_mkkey(rfs4_entry_t u_entry) 28917c478bd9Sstevel@tonic-gate { 28927c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; 28937c478bd9Sstevel@tonic-gate 2894d216dff5SRobert Mastors return (&dsp->rds_delegid); 28957c478bd9Sstevel@tonic-gate } 28967c478bd9Sstevel@tonic-gate 28977c478bd9Sstevel@tonic-gate static bool_t 28987c478bd9Sstevel@tonic-gate rfs4_deleg_state_expiry(rfs4_entry_t u_entry) 28997c478bd9Sstevel@tonic-gate { 29007c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; 29017c478bd9Sstevel@tonic-gate 2902d216dff5SRobert Mastors if (rfs4_dbe_is_invalid(dsp->rds_dbe)) 29037c478bd9Sstevel@tonic-gate return (TRUE); 29047c478bd9Sstevel@tonic-gate 2905eec118a1SMarcel Telka if (dsp->rds_dtype == OPEN_DELEGATE_NONE) 2906eec118a1SMarcel Telka return (TRUE); 2907eec118a1SMarcel Telka 2908d216dff5SRobert Mastors if ((gethrestime_sec() - dsp->rds_client->rc_last_access 2909ed57cab9Srg137905 > rfs4_lease_time)) { 2910d216dff5SRobert Mastors rfs4_dbe_invalidate(dsp->rds_dbe); 2911ed57cab9Srg137905 return (TRUE); 2912ed57cab9Srg137905 } 2913ed57cab9Srg137905 2914ed57cab9Srg137905 return (FALSE); 29157c478bd9Sstevel@tonic-gate } 29167c478bd9Sstevel@tonic-gate 29177c478bd9Sstevel@tonic-gate static bool_t 29187c478bd9Sstevel@tonic-gate rfs4_deleg_state_create(rfs4_entry_t u_entry, void *argp) 29197c478bd9Sstevel@tonic-gate { 29207c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; 2921d216dff5SRobert Mastors rfs4_file_t *fp = ((rfs4_deleg_state_t *)argp)->rds_finfo; 2922d216dff5SRobert Mastors rfs4_client_t *cp = ((rfs4_deleg_state_t *)argp)->rds_client; 29237c478bd9Sstevel@tonic-gate 2924d216dff5SRobert Mastors rfs4_dbe_hold(fp->rf_dbe); 2925d216dff5SRobert Mastors rfs4_dbe_hold(cp->rc_dbe); 29267c478bd9Sstevel@tonic-gate 2927d216dff5SRobert Mastors dsp->rds_delegid = get_stateid(rfs4_dbe_getid(dsp->rds_dbe)); 2928d216dff5SRobert Mastors dsp->rds_delegid.bits.type = DELEGID; 2929d216dff5SRobert Mastors dsp->rds_finfo = fp; 2930d216dff5SRobert Mastors dsp->rds_client = cp; 2931d216dff5SRobert Mastors dsp->rds_dtype = OPEN_DELEGATE_NONE; 29327c478bd9Sstevel@tonic-gate 2933d216dff5SRobert Mastors dsp->rds_time_granted = gethrestime_sec(); /* observability */ 2934d216dff5SRobert Mastors dsp->rds_time_revoked = 0; 29357c478bd9Sstevel@tonic-gate 2936d216dff5SRobert Mastors list_link_init(&dsp->rds_node); 29377c478bd9Sstevel@tonic-gate 29387c478bd9Sstevel@tonic-gate return (TRUE); 29397c478bd9Sstevel@tonic-gate } 29407c478bd9Sstevel@tonic-gate 29417c478bd9Sstevel@tonic-gate static void 29427c478bd9Sstevel@tonic-gate rfs4_deleg_state_destroy(rfs4_entry_t u_entry) 29437c478bd9Sstevel@tonic-gate { 29447c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; 29457c478bd9Sstevel@tonic-gate 2946d216dff5SRobert Mastors /* return delegation if necessary */ 29477c478bd9Sstevel@tonic-gate rfs4_return_deleg(dsp, FALSE); 29487c478bd9Sstevel@tonic-gate 29497c478bd9Sstevel@tonic-gate /* Were done with the file */ 2950d216dff5SRobert Mastors rfs4_file_rele(dsp->rds_finfo); 2951d216dff5SRobert Mastors dsp->rds_finfo = NULL; 29527c478bd9Sstevel@tonic-gate 29537c478bd9Sstevel@tonic-gate /* And now with the openowner */ 2954d216dff5SRobert Mastors rfs4_client_rele(dsp->rds_client); 2955d216dff5SRobert Mastors dsp->rds_client = NULL; 29567c478bd9Sstevel@tonic-gate } 29577c478bd9Sstevel@tonic-gate 29587c478bd9Sstevel@tonic-gate rfs4_deleg_state_t * 29597c478bd9Sstevel@tonic-gate rfs4_finddeleg(rfs4_state_t *sp, bool_t *create) 29607c478bd9Sstevel@tonic-gate { 29617c478bd9Sstevel@tonic-gate rfs4_deleg_state_t ds, *dsp; 29627c478bd9Sstevel@tonic-gate 2963d216dff5SRobert Mastors ds.rds_client = sp->rs_owner->ro_client; 2964d216dff5SRobert Mastors ds.rds_finfo = sp->rs_finfo; 29657c478bd9Sstevel@tonic-gate 29667c478bd9Sstevel@tonic-gate dsp = (rfs4_deleg_state_t *)rfs4_dbsearch(rfs4_deleg_idx, &ds, 29677c478bd9Sstevel@tonic-gate create, &ds, RFS4_DBS_VALID); 29687c478bd9Sstevel@tonic-gate 29697c478bd9Sstevel@tonic-gate return (dsp); 29707c478bd9Sstevel@tonic-gate } 29717c478bd9Sstevel@tonic-gate 29727c478bd9Sstevel@tonic-gate rfs4_deleg_state_t * 29737c478bd9Sstevel@tonic-gate rfs4_finddelegstate(stateid_t *id) 29747c478bd9Sstevel@tonic-gate { 29757c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp; 29767c478bd9Sstevel@tonic-gate bool_t create = FALSE; 29777c478bd9Sstevel@tonic-gate 29787c478bd9Sstevel@tonic-gate dsp = (rfs4_deleg_state_t *)rfs4_dbsearch(rfs4_deleg_state_idx, id, 29797c478bd9Sstevel@tonic-gate &create, NULL, RFS4_DBS_VALID); 29807c478bd9Sstevel@tonic-gate 29817c478bd9Sstevel@tonic-gate return (dsp); 29827c478bd9Sstevel@tonic-gate } 29837c478bd9Sstevel@tonic-gate 29847c478bd9Sstevel@tonic-gate void 29857c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(rfs4_deleg_state_t *dsp) 29867c478bd9Sstevel@tonic-gate { 2987d216dff5SRobert Mastors rfs4_dbe_rele(dsp->rds_dbe); 29887c478bd9Sstevel@tonic-gate } 29897c478bd9Sstevel@tonic-gate 29907c478bd9Sstevel@tonic-gate void 29917c478bd9Sstevel@tonic-gate rfs4_update_lock_sequence(rfs4_lo_state_t *lsp) 29927c478bd9Sstevel@tonic-gate { 29937c478bd9Sstevel@tonic-gate 2994d216dff5SRobert Mastors rfs4_dbe_lock(lsp->rls_dbe); 29957c478bd9Sstevel@tonic-gate 29967c478bd9Sstevel@tonic-gate /* 29977c478bd9Sstevel@tonic-gate * If we are skipping sequence id checking, this means that 29987c478bd9Sstevel@tonic-gate * this is the first lock request and therefore the sequence 29997c478bd9Sstevel@tonic-gate * id does not need to be updated. This only happens on the 30007c478bd9Sstevel@tonic-gate * first lock request for a lockowner 30017c478bd9Sstevel@tonic-gate */ 3002d216dff5SRobert Mastors if (!lsp->rls_skip_seqid_check) 3003d216dff5SRobert Mastors lsp->rls_seqid++; 30047c478bd9Sstevel@tonic-gate 3005d216dff5SRobert Mastors rfs4_dbe_unlock(lsp->rls_dbe); 30067c478bd9Sstevel@tonic-gate } 30077c478bd9Sstevel@tonic-gate 30087c478bd9Sstevel@tonic-gate void 30097c478bd9Sstevel@tonic-gate rfs4_update_lock_resp(rfs4_lo_state_t *lsp, nfs_resop4 *resp) 30107c478bd9Sstevel@tonic-gate { 30117c478bd9Sstevel@tonic-gate 3012d216dff5SRobert Mastors rfs4_dbe_lock(lsp->rls_dbe); 30137c478bd9Sstevel@tonic-gate 3014d216dff5SRobert Mastors rfs4_free_reply(&lsp->rls_reply); 30157c478bd9Sstevel@tonic-gate 3016d216dff5SRobert Mastors rfs4_copy_reply(&lsp->rls_reply, resp); 30177c478bd9Sstevel@tonic-gate 3018d216dff5SRobert Mastors rfs4_dbe_unlock(lsp->rls_dbe); 30197c478bd9Sstevel@tonic-gate } 30207c478bd9Sstevel@tonic-gate 30217c478bd9Sstevel@tonic-gate void 3022d216dff5SRobert Mastors rfs4_free_opens(rfs4_openowner_t *oo, bool_t invalidate, 30237c478bd9Sstevel@tonic-gate bool_t close_of_client) 30247c478bd9Sstevel@tonic-gate { 30257c478bd9Sstevel@tonic-gate rfs4_state_t *sp; 30267c478bd9Sstevel@tonic-gate 3027d216dff5SRobert Mastors rfs4_dbe_lock(oo->ro_dbe); 30287c478bd9Sstevel@tonic-gate 3029d216dff5SRobert Mastors for (sp = list_head(&oo->ro_statelist); sp != NULL; 3030d216dff5SRobert Mastors sp = list_next(&oo->ro_statelist, sp)) { 30317c478bd9Sstevel@tonic-gate rfs4_state_close(sp, FALSE, close_of_client, CRED()); 30327c478bd9Sstevel@tonic-gate if (invalidate == TRUE) 3033d216dff5SRobert Mastors rfs4_dbe_invalidate(sp->rs_dbe); 30347c478bd9Sstevel@tonic-gate } 30357c478bd9Sstevel@tonic-gate 3036d216dff5SRobert Mastors rfs4_dbe_invalidate(oo->ro_dbe); 3037d216dff5SRobert Mastors rfs4_dbe_unlock(oo->ro_dbe); 30387c478bd9Sstevel@tonic-gate } 30397c478bd9Sstevel@tonic-gate 30407c478bd9Sstevel@tonic-gate static uint32_t 30417c478bd9Sstevel@tonic-gate state_owner_file_hash(void *key) 30427c478bd9Sstevel@tonic-gate { 30437c478bd9Sstevel@tonic-gate rfs4_state_t *sp = key; 30447c478bd9Sstevel@tonic-gate 3045d216dff5SRobert Mastors return (ADDRHASH(sp->rs_owner) ^ ADDRHASH(sp->rs_finfo)); 30467c478bd9Sstevel@tonic-gate } 30477c478bd9Sstevel@tonic-gate 30487c478bd9Sstevel@tonic-gate static bool_t 30497c478bd9Sstevel@tonic-gate state_owner_file_compare(rfs4_entry_t u_entry, void *key) 30507c478bd9Sstevel@tonic-gate { 30517c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry; 30527c478bd9Sstevel@tonic-gate rfs4_state_t *arg = key; 30537c478bd9Sstevel@tonic-gate 3054d216dff5SRobert Mastors if (sp->rs_closed == TRUE) 30557c478bd9Sstevel@tonic-gate return (FALSE); 30567c478bd9Sstevel@tonic-gate 3057d216dff5SRobert Mastors return (arg->rs_owner == sp->rs_owner && arg->rs_finfo == sp->rs_finfo); 30587c478bd9Sstevel@tonic-gate } 30597c478bd9Sstevel@tonic-gate 30607c478bd9Sstevel@tonic-gate static void * 30617c478bd9Sstevel@tonic-gate state_owner_file_mkkey(rfs4_entry_t u_entry) 30627c478bd9Sstevel@tonic-gate { 30637c478bd9Sstevel@tonic-gate return (u_entry); 30647c478bd9Sstevel@tonic-gate } 30657c478bd9Sstevel@tonic-gate 30667c478bd9Sstevel@tonic-gate static uint32_t 30677c478bd9Sstevel@tonic-gate state_file_hash(void *key) 30687c478bd9Sstevel@tonic-gate { 30697c478bd9Sstevel@tonic-gate return (ADDRHASH(key)); 30707c478bd9Sstevel@tonic-gate } 30717c478bd9Sstevel@tonic-gate 30727c478bd9Sstevel@tonic-gate static bool_t 30737c478bd9Sstevel@tonic-gate state_file_compare(rfs4_entry_t u_entry, void *key) 30747c478bd9Sstevel@tonic-gate { 30757c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry; 30767c478bd9Sstevel@tonic-gate rfs4_file_t *fp = key; 30777c478bd9Sstevel@tonic-gate 3078d216dff5SRobert Mastors if (sp->rs_closed == TRUE) 30797c478bd9Sstevel@tonic-gate return (FALSE); 30807c478bd9Sstevel@tonic-gate 3081d216dff5SRobert Mastors return (fp == sp->rs_finfo); 30827c478bd9Sstevel@tonic-gate } 30837c478bd9Sstevel@tonic-gate 30847c478bd9Sstevel@tonic-gate static void * 30857c478bd9Sstevel@tonic-gate state_file_mkkey(rfs4_entry_t u_entry) 30867c478bd9Sstevel@tonic-gate { 30877c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry; 30887c478bd9Sstevel@tonic-gate 3089d216dff5SRobert Mastors return (sp->rs_finfo); 30907c478bd9Sstevel@tonic-gate } 30917c478bd9Sstevel@tonic-gate 30927c478bd9Sstevel@tonic-gate rfs4_state_t * 3093d216dff5SRobert Mastors rfs4_findstate_by_owner_file(rfs4_openowner_t *oo, rfs4_file_t *fp, 30947c478bd9Sstevel@tonic-gate bool_t *create) 30957c478bd9Sstevel@tonic-gate { 30967c478bd9Sstevel@tonic-gate rfs4_state_t *sp; 30977c478bd9Sstevel@tonic-gate rfs4_state_t key; 30987c478bd9Sstevel@tonic-gate 3099d216dff5SRobert Mastors key.rs_owner = oo; 3100d216dff5SRobert Mastors key.rs_finfo = fp; 31017c478bd9Sstevel@tonic-gate 31027c478bd9Sstevel@tonic-gate sp = (rfs4_state_t *)rfs4_dbsearch(rfs4_state_owner_file_idx, &key, 31037c478bd9Sstevel@tonic-gate create, &key, RFS4_DBS_VALID); 31047c478bd9Sstevel@tonic-gate 31057c478bd9Sstevel@tonic-gate return (sp); 31067c478bd9Sstevel@tonic-gate } 31077c478bd9Sstevel@tonic-gate 31087c478bd9Sstevel@tonic-gate /* This returns ANY state struct that refers to this file */ 31097c478bd9Sstevel@tonic-gate static rfs4_state_t * 31107c478bd9Sstevel@tonic-gate rfs4_findstate_by_file(rfs4_file_t *fp) 31117c478bd9Sstevel@tonic-gate { 31127c478bd9Sstevel@tonic-gate bool_t create = FALSE; 31137c478bd9Sstevel@tonic-gate 31147c478bd9Sstevel@tonic-gate return ((rfs4_state_t *)rfs4_dbsearch(rfs4_state_file_idx, fp, 31157c478bd9Sstevel@tonic-gate &create, fp, RFS4_DBS_VALID)); 31167c478bd9Sstevel@tonic-gate } 31177c478bd9Sstevel@tonic-gate 31187c478bd9Sstevel@tonic-gate static bool_t 31197c478bd9Sstevel@tonic-gate rfs4_state_expiry(rfs4_entry_t u_entry) 31207c478bd9Sstevel@tonic-gate { 31217c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry; 31227c478bd9Sstevel@tonic-gate 3123d216dff5SRobert Mastors if (rfs4_dbe_is_invalid(sp->rs_dbe)) 31247c478bd9Sstevel@tonic-gate return (TRUE); 31257c478bd9Sstevel@tonic-gate 3126d216dff5SRobert Mastors if (sp->rs_closed == TRUE && 3127d216dff5SRobert Mastors ((gethrestime_sec() - rfs4_dbe_get_timerele(sp->rs_dbe)) 31287c478bd9Sstevel@tonic-gate > rfs4_lease_time)) 31297c478bd9Sstevel@tonic-gate return (TRUE); 31307c478bd9Sstevel@tonic-gate 3131d216dff5SRobert Mastors return ((gethrestime_sec() - sp->rs_owner->ro_client->rc_last_access 31327c478bd9Sstevel@tonic-gate > rfs4_lease_time)); 31337c478bd9Sstevel@tonic-gate } 31347c478bd9Sstevel@tonic-gate 31357c478bd9Sstevel@tonic-gate static bool_t 31367c478bd9Sstevel@tonic-gate rfs4_state_create(rfs4_entry_t u_entry, void *argp) 31377c478bd9Sstevel@tonic-gate { 31387c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry; 3139d216dff5SRobert Mastors rfs4_file_t *fp = ((rfs4_state_t *)argp)->rs_finfo; 3140d216dff5SRobert Mastors rfs4_openowner_t *oo = ((rfs4_state_t *)argp)->rs_owner; 31417c478bd9Sstevel@tonic-gate 3142d216dff5SRobert Mastors rfs4_dbe_hold(fp->rf_dbe); 3143d216dff5SRobert Mastors rfs4_dbe_hold(oo->ro_dbe); 3144d216dff5SRobert Mastors sp->rs_stateid = get_stateid(rfs4_dbe_getid(sp->rs_dbe)); 3145d216dff5SRobert Mastors sp->rs_stateid.bits.type = OPENID; 3146d216dff5SRobert Mastors sp->rs_owner = oo; 3147d216dff5SRobert Mastors sp->rs_finfo = fp; 31487c478bd9Sstevel@tonic-gate 3149d216dff5SRobert Mastors list_create(&sp->rs_lostatelist, sizeof (rfs4_lo_state_t), 3150d216dff5SRobert Mastors offsetof(rfs4_lo_state_t, rls_node)); 31517c478bd9Sstevel@tonic-gate 31527c478bd9Sstevel@tonic-gate /* Insert state on per open owner's list */ 3153d216dff5SRobert Mastors rfs4_dbe_lock(oo->ro_dbe); 3154d216dff5SRobert Mastors list_insert_tail(&oo->ro_statelist, sp); 3155d216dff5SRobert Mastors rfs4_dbe_unlock(oo->ro_dbe); 31567c478bd9Sstevel@tonic-gate 31577c478bd9Sstevel@tonic-gate return (TRUE); 31587c478bd9Sstevel@tonic-gate } 31597c478bd9Sstevel@tonic-gate 31607c478bd9Sstevel@tonic-gate static rfs4_state_t * 3161d216dff5SRobert Mastors rfs4_findstate(stateid_t *id, rfs4_dbsearch_type_t find_invalid, bool_t lock_fp) 31627c478bd9Sstevel@tonic-gate { 31637c478bd9Sstevel@tonic-gate rfs4_state_t *sp; 31647c478bd9Sstevel@tonic-gate bool_t create = FALSE; 31657c478bd9Sstevel@tonic-gate 31667c478bd9Sstevel@tonic-gate sp = (rfs4_state_t *)rfs4_dbsearch(rfs4_state_idx, id, 31677c478bd9Sstevel@tonic-gate &create, NULL, find_invalid); 31687c478bd9Sstevel@tonic-gate if (lock_fp == TRUE && sp != NULL) 3169d216dff5SRobert Mastors rw_enter(&sp->rs_finfo->rf_file_rwlock, RW_READER); 31707c478bd9Sstevel@tonic-gate 31717c478bd9Sstevel@tonic-gate return (sp); 31727c478bd9Sstevel@tonic-gate } 31737c478bd9Sstevel@tonic-gate 31747c478bd9Sstevel@tonic-gate void 3175d216dff5SRobert Mastors rfs4_state_close(rfs4_state_t *sp, bool_t lock_held, bool_t close_of_client, 3176d216dff5SRobert Mastors cred_t *cr) 31777c478bd9Sstevel@tonic-gate { 31787c478bd9Sstevel@tonic-gate /* Remove the associated lo_state owners */ 31797c478bd9Sstevel@tonic-gate if (!lock_held) 3180d216dff5SRobert Mastors rfs4_dbe_lock(sp->rs_dbe); 3181c420ca07Smaheshvs 3182c420ca07Smaheshvs /* 3183c420ca07Smaheshvs * If refcnt == 0, the dbe is about to be destroyed. 3184c420ca07Smaheshvs * lock state will be released by the reaper thread. 3185c420ca07Smaheshvs */ 3186c420ca07Smaheshvs 3187d216dff5SRobert Mastors if (rfs4_dbe_refcnt(sp->rs_dbe) > 0) { 3188d216dff5SRobert Mastors if (sp->rs_closed == FALSE) { 31897c478bd9Sstevel@tonic-gate rfs4_release_share_lock_state(sp, cr, close_of_client); 3190d216dff5SRobert Mastors sp->rs_closed = TRUE; 31917c478bd9Sstevel@tonic-gate } 3192c420ca07Smaheshvs } 3193c420ca07Smaheshvs 31947c478bd9Sstevel@tonic-gate if (!lock_held) 3195d216dff5SRobert Mastors rfs4_dbe_unlock(sp->rs_dbe); 31967c478bd9Sstevel@tonic-gate } 31977c478bd9Sstevel@tonic-gate 31987c478bd9Sstevel@tonic-gate /* 31997c478bd9Sstevel@tonic-gate * Remove all state associated with the given client. 32007c478bd9Sstevel@tonic-gate */ 32017c478bd9Sstevel@tonic-gate void 32027c478bd9Sstevel@tonic-gate rfs4_client_state_remove(rfs4_client_t *cp) 32037c478bd9Sstevel@tonic-gate { 3204d216dff5SRobert Mastors rfs4_openowner_t *oo; 32057c478bd9Sstevel@tonic-gate 3206d216dff5SRobert Mastors rfs4_dbe_lock(cp->rc_dbe); 32077c478bd9Sstevel@tonic-gate 3208d216dff5SRobert Mastors for (oo = list_head(&cp->rc_openownerlist); oo != NULL; 3209d216dff5SRobert Mastors oo = list_next(&cp->rc_openownerlist, oo)) { 3210d216dff5SRobert Mastors rfs4_free_opens(oo, TRUE, TRUE); 32117c478bd9Sstevel@tonic-gate } 32127c478bd9Sstevel@tonic-gate 3213d216dff5SRobert Mastors rfs4_dbe_unlock(cp->rc_dbe); 32147c478bd9Sstevel@tonic-gate } 32157c478bd9Sstevel@tonic-gate 32167c478bd9Sstevel@tonic-gate void 32177c478bd9Sstevel@tonic-gate rfs4_client_close(rfs4_client_t *cp) 32187c478bd9Sstevel@tonic-gate { 32197c478bd9Sstevel@tonic-gate /* Mark client as going away. */ 3220d216dff5SRobert Mastors rfs4_dbe_lock(cp->rc_dbe); 3221d216dff5SRobert Mastors rfs4_dbe_invalidate(cp->rc_dbe); 3222d216dff5SRobert Mastors rfs4_dbe_unlock(cp->rc_dbe); 32237c478bd9Sstevel@tonic-gate 32247c478bd9Sstevel@tonic-gate rfs4_client_state_remove(cp); 32257c478bd9Sstevel@tonic-gate 32267c478bd9Sstevel@tonic-gate /* Release the client */ 32277c478bd9Sstevel@tonic-gate rfs4_client_rele(cp); 32287c478bd9Sstevel@tonic-gate } 32297c478bd9Sstevel@tonic-gate 32307c478bd9Sstevel@tonic-gate nfsstat4 32317c478bd9Sstevel@tonic-gate rfs4_check_clientid(clientid4 *cp, int setclid_confirm) 32327c478bd9Sstevel@tonic-gate { 32337c478bd9Sstevel@tonic-gate cid *cidp = (cid *) cp; 32347c478bd9Sstevel@tonic-gate 32357c478bd9Sstevel@tonic-gate /* 32367c478bd9Sstevel@tonic-gate * If we are booted as a cluster node, check the embedded nodeid. 32377c478bd9Sstevel@tonic-gate * If it indicates that this clientid was generated on another node, 32387c478bd9Sstevel@tonic-gate * inform the client accordingly. 32397c478bd9Sstevel@tonic-gate */ 32407c478bd9Sstevel@tonic-gate if (cluster_bootflags & CLUSTER_BOOTED && foreign_clientid(cidp)) 32417c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_CLIENTID); 32427c478bd9Sstevel@tonic-gate 32437c478bd9Sstevel@tonic-gate /* 32447c478bd9Sstevel@tonic-gate * If the server start time matches the time provided 32457c478bd9Sstevel@tonic-gate * by the client (via the clientid) and this is NOT a 32467c478bd9Sstevel@tonic-gate * setclientid_confirm then return EXPIRED. 32477c478bd9Sstevel@tonic-gate */ 32487c478bd9Sstevel@tonic-gate if (!setclid_confirm && cidp->impl_id.start_time == rfs4_start_time) 32497c478bd9Sstevel@tonic-gate return (NFS4ERR_EXPIRED); 32507c478bd9Sstevel@tonic-gate 32517c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_CLIENTID); 32527c478bd9Sstevel@tonic-gate } 32537c478bd9Sstevel@tonic-gate 32547c478bd9Sstevel@tonic-gate /* 32557c478bd9Sstevel@tonic-gate * This is used when a stateid has not been found amongst the 32567c478bd9Sstevel@tonic-gate * current server's state. Check the stateid to see if it 32577c478bd9Sstevel@tonic-gate * was from this server instantiation or not. 32587c478bd9Sstevel@tonic-gate */ 32597c478bd9Sstevel@tonic-gate static nfsstat4 32607c478bd9Sstevel@tonic-gate what_stateid_error(stateid_t *id, stateid_type_t type) 32617c478bd9Sstevel@tonic-gate { 32627c478bd9Sstevel@tonic-gate /* If we are booted as a cluster node, was stateid locally generated? */ 32637c478bd9Sstevel@tonic-gate if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id)) 32647c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_STATEID); 32657c478bd9Sstevel@tonic-gate 32667c478bd9Sstevel@tonic-gate /* If types don't match then no use checking further */ 32677c478bd9Sstevel@tonic-gate if (type != id->bits.type) 32687c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 32697c478bd9Sstevel@tonic-gate 3270*25a1318cSMarcel Telka /* From a different server instantiation, return STALE */ 3271*25a1318cSMarcel Telka if (id->bits.boottime != rfs4_start_time) 32727c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_STATEID); 32737c478bd9Sstevel@tonic-gate 32747c478bd9Sstevel@tonic-gate /* 32757c478bd9Sstevel@tonic-gate * From this server but the state is most likely beyond lease 32767c478bd9Sstevel@tonic-gate * timeout: return NFS4ERR_EXPIRED. However, there is the 32777c478bd9Sstevel@tonic-gate * case of a delegation stateid. For delegations, there is a 32787c478bd9Sstevel@tonic-gate * case where the state can be removed without the client's 32797c478bd9Sstevel@tonic-gate * knowledge/consent: revocation. In the case of delegation 32807c478bd9Sstevel@tonic-gate * revocation, the delegation state will be removed and will 32817c478bd9Sstevel@tonic-gate * not be found. If the client does something like a 32827c478bd9Sstevel@tonic-gate * DELEGRETURN or even a READ/WRITE with a delegatoin stateid 32837c478bd9Sstevel@tonic-gate * that has been revoked, the server should return BAD_STATEID 32847c478bd9Sstevel@tonic-gate * instead of the more common EXPIRED error. 32857c478bd9Sstevel@tonic-gate */ 32867c478bd9Sstevel@tonic-gate if (id->bits.boottime == rfs4_start_time) { 32877c478bd9Sstevel@tonic-gate if (type == DELEGID) 32887c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 32897c478bd9Sstevel@tonic-gate else 32907c478bd9Sstevel@tonic-gate return (NFS4ERR_EXPIRED); 32917c478bd9Sstevel@tonic-gate } 32927c478bd9Sstevel@tonic-gate 32937c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 32947c478bd9Sstevel@tonic-gate } 32957c478bd9Sstevel@tonic-gate 32967c478bd9Sstevel@tonic-gate /* 32977c478bd9Sstevel@tonic-gate * Used later on to find the various state structs. When called from 32987c478bd9Sstevel@tonic-gate * rfs4_check_stateid()->rfs4_get_all_state(), no file struct lock is 32997c478bd9Sstevel@tonic-gate * taken (it is not needed) and helps on the read/write path with 33007c478bd9Sstevel@tonic-gate * respect to performance. 33017c478bd9Sstevel@tonic-gate */ 33027c478bd9Sstevel@tonic-gate static nfsstat4 33037c478bd9Sstevel@tonic-gate rfs4_get_state_lockit(stateid4 *stateid, rfs4_state_t **spp, 33047c478bd9Sstevel@tonic-gate rfs4_dbsearch_type_t find_invalid, bool_t lock_fp) 33057c478bd9Sstevel@tonic-gate { 33067c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid; 33077c478bd9Sstevel@tonic-gate rfs4_state_t *sp; 33087c478bd9Sstevel@tonic-gate 33097c478bd9Sstevel@tonic-gate *spp = NULL; 33107c478bd9Sstevel@tonic-gate 33117c478bd9Sstevel@tonic-gate /* If we are booted as a cluster node, was stateid locally generated? */ 33127c478bd9Sstevel@tonic-gate if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id)) 33137c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_STATEID); 33147c478bd9Sstevel@tonic-gate 33157c478bd9Sstevel@tonic-gate sp = rfs4_findstate(id, find_invalid, lock_fp); 33167c478bd9Sstevel@tonic-gate if (sp == NULL) { 33177c478bd9Sstevel@tonic-gate return (what_stateid_error(id, OPENID)); 33187c478bd9Sstevel@tonic-gate } 33197c478bd9Sstevel@tonic-gate 3320d216dff5SRobert Mastors if (rfs4_lease_expired(sp->rs_owner->ro_client)) { 33217c478bd9Sstevel@tonic-gate if (lock_fp == TRUE) 33227c478bd9Sstevel@tonic-gate rfs4_state_rele(sp); 33237c478bd9Sstevel@tonic-gate else 33247c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 33257c478bd9Sstevel@tonic-gate return (NFS4ERR_EXPIRED); 33267c478bd9Sstevel@tonic-gate } 33277c478bd9Sstevel@tonic-gate 33287c478bd9Sstevel@tonic-gate *spp = sp; 33297c478bd9Sstevel@tonic-gate 33307c478bd9Sstevel@tonic-gate return (NFS4_OK); 33317c478bd9Sstevel@tonic-gate } 33327c478bd9Sstevel@tonic-gate 33337c478bd9Sstevel@tonic-gate nfsstat4 33347c478bd9Sstevel@tonic-gate rfs4_get_state(stateid4 *stateid, rfs4_state_t **spp, 33357c478bd9Sstevel@tonic-gate rfs4_dbsearch_type_t find_invalid) 33367c478bd9Sstevel@tonic-gate { 33377c478bd9Sstevel@tonic-gate return (rfs4_get_state_lockit(stateid, spp, find_invalid, TRUE)); 33387c478bd9Sstevel@tonic-gate } 33397c478bd9Sstevel@tonic-gate 33407c478bd9Sstevel@tonic-gate int 33417c478bd9Sstevel@tonic-gate rfs4_check_stateid_seqid(rfs4_state_t *sp, stateid4 *stateid) 33427c478bd9Sstevel@tonic-gate { 33437c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid; 33447c478bd9Sstevel@tonic-gate 3345d216dff5SRobert Mastors if (rfs4_lease_expired(sp->rs_owner->ro_client)) 33467c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_EXPIRED); 33477c478bd9Sstevel@tonic-gate 33487c478bd9Sstevel@tonic-gate /* Stateid is some time in the future - that's bad */ 3349d216dff5SRobert Mastors if (sp->rs_stateid.bits.chgseq < id->bits.chgseq) 33507c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_BAD); 33517c478bd9Sstevel@tonic-gate 3352d216dff5SRobert Mastors if (sp->rs_stateid.bits.chgseq == id->bits.chgseq + 1) 33537c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_REPLAY); 33547c478bd9Sstevel@tonic-gate 33557c478bd9Sstevel@tonic-gate /* Stateid is some time in the past - that's old */ 3356d216dff5SRobert Mastors if (sp->rs_stateid.bits.chgseq > id->bits.chgseq) 33577c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_OLD); 33587c478bd9Sstevel@tonic-gate 33597c478bd9Sstevel@tonic-gate /* Caller needs to know about confirmation before closure */ 3360d216dff5SRobert Mastors if (sp->rs_owner->ro_need_confirm) 33617c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_UNCONFIRMED); 33627c478bd9Sstevel@tonic-gate 3363d216dff5SRobert Mastors if (sp->rs_closed == TRUE) 33647c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_CLOSED); 33657c478bd9Sstevel@tonic-gate 33667c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_OKAY); 33677c478bd9Sstevel@tonic-gate } 33687c478bd9Sstevel@tonic-gate 33697c478bd9Sstevel@tonic-gate int 33707c478bd9Sstevel@tonic-gate rfs4_check_lo_stateid_seqid(rfs4_lo_state_t *lsp, stateid4 *stateid) 33717c478bd9Sstevel@tonic-gate { 33727c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid; 33737c478bd9Sstevel@tonic-gate 3374d216dff5SRobert Mastors if (rfs4_lease_expired(lsp->rls_state->rs_owner->ro_client)) 33757c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_EXPIRED); 33767c478bd9Sstevel@tonic-gate 33777c478bd9Sstevel@tonic-gate /* Stateid is some time in the future - that's bad */ 3378d216dff5SRobert Mastors if (lsp->rls_lockid.bits.chgseq < id->bits.chgseq) 33797c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_BAD); 33807c478bd9Sstevel@tonic-gate 3381d216dff5SRobert Mastors if (lsp->rls_lockid.bits.chgseq == id->bits.chgseq + 1) 33827c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_REPLAY); 33837c478bd9Sstevel@tonic-gate 33847c478bd9Sstevel@tonic-gate /* Stateid is some time in the past - that's old */ 3385d216dff5SRobert Mastors if (lsp->rls_lockid.bits.chgseq > id->bits.chgseq) 33867c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_OLD); 33877c478bd9Sstevel@tonic-gate 3388d216dff5SRobert Mastors if (lsp->rls_state->rs_closed == TRUE) 3389d216dff5SRobert Mastors return (NFS4_CHECK_STATEID_CLOSED); 3390d216dff5SRobert Mastors 33917c478bd9Sstevel@tonic-gate return (NFS4_CHECK_STATEID_OKAY); 33927c478bd9Sstevel@tonic-gate } 33937c478bd9Sstevel@tonic-gate 33947c478bd9Sstevel@tonic-gate nfsstat4 33957c478bd9Sstevel@tonic-gate rfs4_get_deleg_state(stateid4 *stateid, rfs4_deleg_state_t **dspp) 33967c478bd9Sstevel@tonic-gate { 33977c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid; 33987c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp; 33997c478bd9Sstevel@tonic-gate 34007c478bd9Sstevel@tonic-gate *dspp = NULL; 34017c478bd9Sstevel@tonic-gate 34027c478bd9Sstevel@tonic-gate /* If we are booted as a cluster node, was stateid locally generated? */ 34037c478bd9Sstevel@tonic-gate if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id)) 34047c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_STATEID); 34057c478bd9Sstevel@tonic-gate 34067c478bd9Sstevel@tonic-gate dsp = rfs4_finddelegstate(id); 34077c478bd9Sstevel@tonic-gate if (dsp == NULL) { 34087c478bd9Sstevel@tonic-gate return (what_stateid_error(id, DELEGID)); 34097c478bd9Sstevel@tonic-gate } 34107c478bd9Sstevel@tonic-gate 3411d216dff5SRobert Mastors if (rfs4_lease_expired(dsp->rds_client)) { 34127c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(dsp); 34137c478bd9Sstevel@tonic-gate return (NFS4ERR_EXPIRED); 34147c478bd9Sstevel@tonic-gate } 34157c478bd9Sstevel@tonic-gate 34167c478bd9Sstevel@tonic-gate *dspp = dsp; 34177c478bd9Sstevel@tonic-gate 34187c478bd9Sstevel@tonic-gate return (NFS4_OK); 34197c478bd9Sstevel@tonic-gate } 34207c478bd9Sstevel@tonic-gate 34217c478bd9Sstevel@tonic-gate nfsstat4 34227c478bd9Sstevel@tonic-gate rfs4_get_lo_state(stateid4 *stateid, rfs4_lo_state_t **lspp, bool_t lock_fp) 34237c478bd9Sstevel@tonic-gate { 34247c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid; 34257c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp; 34267c478bd9Sstevel@tonic-gate 34277c478bd9Sstevel@tonic-gate *lspp = NULL; 34287c478bd9Sstevel@tonic-gate 34297c478bd9Sstevel@tonic-gate /* If we are booted as a cluster node, was stateid locally generated? */ 34307c478bd9Sstevel@tonic-gate if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id)) 34317c478bd9Sstevel@tonic-gate return (NFS4ERR_STALE_STATEID); 34327c478bd9Sstevel@tonic-gate 34337c478bd9Sstevel@tonic-gate lsp = rfs4_findlo_state(id, lock_fp); 34347c478bd9Sstevel@tonic-gate if (lsp == NULL) { 34357c478bd9Sstevel@tonic-gate return (what_stateid_error(id, LOCKID)); 34367c478bd9Sstevel@tonic-gate } 34377c478bd9Sstevel@tonic-gate 3438d216dff5SRobert Mastors if (rfs4_lease_expired(lsp->rls_state->rs_owner->ro_client)) { 34397c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(lsp, lock_fp); 34407c478bd9Sstevel@tonic-gate return (NFS4ERR_EXPIRED); 34417c478bd9Sstevel@tonic-gate } 34427c478bd9Sstevel@tonic-gate 34437c478bd9Sstevel@tonic-gate *lspp = lsp; 34447c478bd9Sstevel@tonic-gate 34457c478bd9Sstevel@tonic-gate return (NFS4_OK); 34467c478bd9Sstevel@tonic-gate } 34477c478bd9Sstevel@tonic-gate 34487c478bd9Sstevel@tonic-gate static nfsstat4 34497c478bd9Sstevel@tonic-gate rfs4_get_all_state(stateid4 *sid, rfs4_state_t **spp, 3450d216dff5SRobert Mastors rfs4_deleg_state_t **dspp, rfs4_lo_state_t **lspp) 34517c478bd9Sstevel@tonic-gate { 34527c478bd9Sstevel@tonic-gate rfs4_state_t *sp = NULL; 34537c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = NULL; 3454d216dff5SRobert Mastors rfs4_lo_state_t *lsp = NULL; 34557c478bd9Sstevel@tonic-gate stateid_t *id; 34567c478bd9Sstevel@tonic-gate nfsstat4 status; 34577c478bd9Sstevel@tonic-gate 3458d216dff5SRobert Mastors *spp = NULL; *dspp = NULL; *lspp = NULL; 34597c478bd9Sstevel@tonic-gate 34607c478bd9Sstevel@tonic-gate id = (stateid_t *)sid; 34617c478bd9Sstevel@tonic-gate switch (id->bits.type) { 34627c478bd9Sstevel@tonic-gate case OPENID: 34637c478bd9Sstevel@tonic-gate status = rfs4_get_state_lockit(sid, &sp, FALSE, FALSE); 34647c478bd9Sstevel@tonic-gate break; 34657c478bd9Sstevel@tonic-gate case DELEGID: 34667c478bd9Sstevel@tonic-gate status = rfs4_get_deleg_state(sid, &dsp); 34677c478bd9Sstevel@tonic-gate break; 34687c478bd9Sstevel@tonic-gate case LOCKID: 3469d216dff5SRobert Mastors status = rfs4_get_lo_state(sid, &lsp, FALSE); 34707c478bd9Sstevel@tonic-gate if (status == NFS4_OK) { 3471d216dff5SRobert Mastors sp = lsp->rls_state; 3472d216dff5SRobert Mastors rfs4_dbe_hold(sp->rs_dbe); 34737c478bd9Sstevel@tonic-gate } 34747c478bd9Sstevel@tonic-gate break; 34757c478bd9Sstevel@tonic-gate default: 34767c478bd9Sstevel@tonic-gate status = NFS4ERR_BAD_STATEID; 34777c478bd9Sstevel@tonic-gate } 34787c478bd9Sstevel@tonic-gate 34797c478bd9Sstevel@tonic-gate if (status == NFS4_OK) { 34807c478bd9Sstevel@tonic-gate *spp = sp; 34817c478bd9Sstevel@tonic-gate *dspp = dsp; 3482d216dff5SRobert Mastors *lspp = lsp; 34837c478bd9Sstevel@tonic-gate } 34847c478bd9Sstevel@tonic-gate 34857c478bd9Sstevel@tonic-gate return (status); 34867c478bd9Sstevel@tonic-gate } 34877c478bd9Sstevel@tonic-gate 34887c478bd9Sstevel@tonic-gate /* 34897c478bd9Sstevel@tonic-gate * Given the I/O mode (FREAD or FWRITE), this checks whether the 34907c478bd9Sstevel@tonic-gate * rfs4_state_t struct has access to do this operation and if so 34917c478bd9Sstevel@tonic-gate * return NFS4_OK; otherwise the proper NFSv4 error is returned. 34927c478bd9Sstevel@tonic-gate */ 34937c478bd9Sstevel@tonic-gate nfsstat4 34947c478bd9Sstevel@tonic-gate rfs4_state_has_access(rfs4_state_t *sp, int mode, vnode_t *vp) 34957c478bd9Sstevel@tonic-gate { 34967c478bd9Sstevel@tonic-gate nfsstat4 stat = NFS4_OK; 34977c478bd9Sstevel@tonic-gate rfs4_file_t *fp; 34987c478bd9Sstevel@tonic-gate bool_t create = FALSE; 34997c478bd9Sstevel@tonic-gate 3500d216dff5SRobert Mastors rfs4_dbe_lock(sp->rs_dbe); 35017c478bd9Sstevel@tonic-gate if (mode == FWRITE) { 3502d216dff5SRobert Mastors if (!(sp->rs_share_access & OPEN4_SHARE_ACCESS_WRITE)) { 35037c478bd9Sstevel@tonic-gate stat = NFS4ERR_OPENMODE; 35047c478bd9Sstevel@tonic-gate } 35057c478bd9Sstevel@tonic-gate } else if (mode == FREAD) { 3506d216dff5SRobert Mastors if (!(sp->rs_share_access & OPEN4_SHARE_ACCESS_READ)) { 35077c478bd9Sstevel@tonic-gate /* 35087c478bd9Sstevel@tonic-gate * If we have OPENed the file with DENYing access 35097c478bd9Sstevel@tonic-gate * to both READ and WRITE then no one else could 35107c478bd9Sstevel@tonic-gate * have OPENed the file, hence no conflicting READ 35117c478bd9Sstevel@tonic-gate * deny. This check is merely an optimization. 35127c478bd9Sstevel@tonic-gate */ 3513d216dff5SRobert Mastors if (sp->rs_share_deny == OPEN4_SHARE_DENY_BOTH) 35147c478bd9Sstevel@tonic-gate goto out; 35157c478bd9Sstevel@tonic-gate 35167c478bd9Sstevel@tonic-gate /* Check against file struct's DENY mode */ 35177c478bd9Sstevel@tonic-gate fp = rfs4_findfile(vp, NULL, &create); 35187c478bd9Sstevel@tonic-gate if (fp != NULL) { 35197c478bd9Sstevel@tonic-gate int deny_read = 0; 3520d216dff5SRobert Mastors rfs4_dbe_lock(fp->rf_dbe); 35217c478bd9Sstevel@tonic-gate /* 35227c478bd9Sstevel@tonic-gate * Check if any other open owner has the file 35237c478bd9Sstevel@tonic-gate * OPENed with deny READ. 35247c478bd9Sstevel@tonic-gate */ 3525d216dff5SRobert Mastors if (sp->rs_share_deny & OPEN4_SHARE_DENY_READ) 35267c478bd9Sstevel@tonic-gate deny_read = 1; 3527eec118a1SMarcel Telka ASSERT(fp->rf_deny_read >= deny_read); 3528eec118a1SMarcel Telka if (fp->rf_deny_read > deny_read) 35297c478bd9Sstevel@tonic-gate stat = NFS4ERR_OPENMODE; 3530d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe); 35317c478bd9Sstevel@tonic-gate rfs4_file_rele(fp); 35327c478bd9Sstevel@tonic-gate } 35337c478bd9Sstevel@tonic-gate } 35347c478bd9Sstevel@tonic-gate } else { 35357c478bd9Sstevel@tonic-gate /* Illegal I/O mode */ 35367c478bd9Sstevel@tonic-gate stat = NFS4ERR_INVAL; 35377c478bd9Sstevel@tonic-gate } 35387c478bd9Sstevel@tonic-gate out: 3539d216dff5SRobert Mastors rfs4_dbe_unlock(sp->rs_dbe); 35407c478bd9Sstevel@tonic-gate return (stat); 35417c478bd9Sstevel@tonic-gate } 35427c478bd9Sstevel@tonic-gate 35437c478bd9Sstevel@tonic-gate /* 35447c478bd9Sstevel@tonic-gate * Given the I/O mode (FREAD or FWRITE), the vnode, the stateid and whether 3545da6c28aaSamw * the file is being truncated, return NFS4_OK if allowed or appropriate 35467c478bd9Sstevel@tonic-gate * V4 error if not. Note NFS4ERR_DELAY will be returned and a recall on 35477c478bd9Sstevel@tonic-gate * the associated file will be done if the I/O is not consistent with any 35487c478bd9Sstevel@tonic-gate * delegation in effect on the file. Should be holding VOP_RWLOCK, either 3549da6c28aaSamw * as reader or writer as appropriate. rfs4_op_open will acquire the 35507c478bd9Sstevel@tonic-gate * VOP_RWLOCK as writer when setting up delegation. If the stateid is bad 35517c478bd9Sstevel@tonic-gate * this routine will return NFS4ERR_BAD_STATEID. In addition, through the 35527c478bd9Sstevel@tonic-gate * deleg parameter, we will return whether a write delegation is held by 35537c478bd9Sstevel@tonic-gate * the client associated with this stateid. 35547c478bd9Sstevel@tonic-gate * If the server instance associated with the relevant client is in its 35557c478bd9Sstevel@tonic-gate * grace period, return NFS4ERR_GRACE. 35567c478bd9Sstevel@tonic-gate */ 35577c478bd9Sstevel@tonic-gate 35587c478bd9Sstevel@tonic-gate nfsstat4 35597c478bd9Sstevel@tonic-gate rfs4_check_stateid(int mode, vnode_t *vp, 35607c478bd9Sstevel@tonic-gate stateid4 *stateid, bool_t trunc, bool_t *deleg, 3561da6c28aaSamw bool_t do_access, caller_context_t *ct) 35627c478bd9Sstevel@tonic-gate { 35637c478bd9Sstevel@tonic-gate rfs4_file_t *fp; 35647c478bd9Sstevel@tonic-gate bool_t create = FALSE; 35657c478bd9Sstevel@tonic-gate rfs4_state_t *sp; 35667c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp; 35677c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp; 35687c478bd9Sstevel@tonic-gate stateid_t *id = (stateid_t *)stateid; 35697c478bd9Sstevel@tonic-gate nfsstat4 stat = NFS4_OK; 35707c478bd9Sstevel@tonic-gate 3571da6c28aaSamw if (ct != NULL) { 3572da6c28aaSamw ct->cc_sysid = 0; 3573da6c28aaSamw ct->cc_pid = 0; 3574da6c28aaSamw ct->cc_caller_id = nfs4_srv_caller_id; 357562b9fcbeSjwahlig ct->cc_flags = CC_DONTBLOCK; 3576da6c28aaSamw } 3577da6c28aaSamw 35787c478bd9Sstevel@tonic-gate if (ISSPECIAL(stateid)) { 35797c478bd9Sstevel@tonic-gate fp = rfs4_findfile(vp, NULL, &create); 35807c478bd9Sstevel@tonic-gate if (fp == NULL) 35817c478bd9Sstevel@tonic-gate return (NFS4_OK); 3582d216dff5SRobert Mastors if (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_NONE) { 35837c478bd9Sstevel@tonic-gate rfs4_file_rele(fp); 35847c478bd9Sstevel@tonic-gate return (NFS4_OK); 35857c478bd9Sstevel@tonic-gate } 35867c478bd9Sstevel@tonic-gate if (mode == FWRITE || 3587d216dff5SRobert Mastors fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_WRITE) { 35887c478bd9Sstevel@tonic-gate rfs4_recall_deleg(fp, trunc, NULL); 35897c478bd9Sstevel@tonic-gate rfs4_file_rele(fp); 35907c478bd9Sstevel@tonic-gate return (NFS4ERR_DELAY); 35917c478bd9Sstevel@tonic-gate } 35927c478bd9Sstevel@tonic-gate rfs4_file_rele(fp); 35937c478bd9Sstevel@tonic-gate return (NFS4_OK); 35947c478bd9Sstevel@tonic-gate } else { 35957c478bd9Sstevel@tonic-gate stat = rfs4_get_all_state(stateid, &sp, &dsp, &lsp); 35967c478bd9Sstevel@tonic-gate if (stat != NFS4_OK) 35977c478bd9Sstevel@tonic-gate return (stat); 35987c478bd9Sstevel@tonic-gate if (lsp != NULL) { 35997c478bd9Sstevel@tonic-gate /* Is associated server instance in its grace period? */ 3600d216dff5SRobert Mastors if (rfs4_clnt_in_grace(lsp->rls_locker->rl_client)) { 36017c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(lsp, FALSE); 36027c478bd9Sstevel@tonic-gate if (sp != NULL) 36037c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 36047c478bd9Sstevel@tonic-gate return (NFS4ERR_GRACE); 36057c478bd9Sstevel@tonic-gate } 36067c478bd9Sstevel@tonic-gate if (id->bits.type == LOCKID) { 36077c478bd9Sstevel@tonic-gate /* Seqid in the future? - that's bad */ 3608d216dff5SRobert Mastors if (lsp->rls_lockid.bits.chgseq < 36097c478bd9Sstevel@tonic-gate id->bits.chgseq) { 36107c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(lsp, FALSE); 36117c478bd9Sstevel@tonic-gate if (sp != NULL) 36127c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 36137c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 36147c478bd9Sstevel@tonic-gate } 36157c478bd9Sstevel@tonic-gate /* Seqid in the past? - that's old */ 3616d216dff5SRobert Mastors if (lsp->rls_lockid.bits.chgseq > 36177c478bd9Sstevel@tonic-gate id->bits.chgseq) { 36187c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(lsp, FALSE); 36197c478bd9Sstevel@tonic-gate if (sp != NULL) 36207c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 36217c478bd9Sstevel@tonic-gate return (NFS4ERR_OLD_STATEID); 36227c478bd9Sstevel@tonic-gate } 36237c478bd9Sstevel@tonic-gate /* Ensure specified filehandle matches */ 3624d216dff5SRobert Mastors if (lsp->rls_state->rs_finfo->rf_vp != vp) { 36257c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(lsp, FALSE); 36267c478bd9Sstevel@tonic-gate if (sp != NULL) 36277c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 36287c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 36297c478bd9Sstevel@tonic-gate } 36307c478bd9Sstevel@tonic-gate } 3631da6c28aaSamw if (ct != NULL) { 3632d216dff5SRobert Mastors ct->cc_sysid = 3633d216dff5SRobert Mastors lsp->rls_locker->rl_client->rc_sysidt; 3634d216dff5SRobert Mastors ct->cc_pid = lsp->rls_locker->rl_pid; 3635da6c28aaSamw } 36367c478bd9Sstevel@tonic-gate rfs4_lo_state_rele(lsp, FALSE); 36377c478bd9Sstevel@tonic-gate } 36387c478bd9Sstevel@tonic-gate 36397c478bd9Sstevel@tonic-gate /* Stateid provided was an "open" stateid */ 36407c478bd9Sstevel@tonic-gate if (sp != NULL) { 36417c478bd9Sstevel@tonic-gate /* Is associated server instance in its grace period? */ 3642d216dff5SRobert Mastors if (rfs4_clnt_in_grace(sp->rs_owner->ro_client)) { 36437c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 36447c478bd9Sstevel@tonic-gate return (NFS4ERR_GRACE); 36457c478bd9Sstevel@tonic-gate } 36467c478bd9Sstevel@tonic-gate if (id->bits.type == OPENID) { 36477c478bd9Sstevel@tonic-gate /* Seqid in the future? - that's bad */ 3648d216dff5SRobert Mastors if (sp->rs_stateid.bits.chgseq < 36497c478bd9Sstevel@tonic-gate id->bits.chgseq) { 36507c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 36517c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 36527c478bd9Sstevel@tonic-gate } 36537c478bd9Sstevel@tonic-gate /* Seqid in the past - that's old */ 3654d216dff5SRobert Mastors if (sp->rs_stateid.bits.chgseq > 36557c478bd9Sstevel@tonic-gate id->bits.chgseq) { 36567c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 36577c478bd9Sstevel@tonic-gate return (NFS4ERR_OLD_STATEID); 36587c478bd9Sstevel@tonic-gate } 36597c478bd9Sstevel@tonic-gate } 36607c478bd9Sstevel@tonic-gate /* Ensure specified filehandle matches */ 3661d216dff5SRobert Mastors if (sp->rs_finfo->rf_vp != vp) { 36627c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 36637c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 36647c478bd9Sstevel@tonic-gate } 36657c478bd9Sstevel@tonic-gate 3666d216dff5SRobert Mastors if (sp->rs_owner->ro_need_confirm) { 36677c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 36687c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 36697c478bd9Sstevel@tonic-gate } 36707c478bd9Sstevel@tonic-gate 3671d216dff5SRobert Mastors if (sp->rs_closed == TRUE) { 36727c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 36737c478bd9Sstevel@tonic-gate return (NFS4ERR_OLD_STATEID); 36747c478bd9Sstevel@tonic-gate } 36757c478bd9Sstevel@tonic-gate 36767c478bd9Sstevel@tonic-gate if (do_access) 36777c478bd9Sstevel@tonic-gate stat = rfs4_state_has_access(sp, mode, vp); 36787c478bd9Sstevel@tonic-gate else 36797c478bd9Sstevel@tonic-gate stat = NFS4_OK; 36807c478bd9Sstevel@tonic-gate 36817c478bd9Sstevel@tonic-gate /* 36827c478bd9Sstevel@tonic-gate * Return whether this state has write 36837c478bd9Sstevel@tonic-gate * delegation if desired 36847c478bd9Sstevel@tonic-gate */ 3685d216dff5SRobert Mastors if (deleg && (sp->rs_finfo->rf_dinfo.rd_dtype == 3686d216dff5SRobert Mastors OPEN_DELEGATE_WRITE)) 36877c478bd9Sstevel@tonic-gate *deleg = TRUE; 36887c478bd9Sstevel@tonic-gate 36897c478bd9Sstevel@tonic-gate /* 36907c478bd9Sstevel@tonic-gate * We got a valid stateid, so we update the 36917c478bd9Sstevel@tonic-gate * lease on the client. Ideally we would like 36927c478bd9Sstevel@tonic-gate * to do this after the calling op succeeds, 36937c478bd9Sstevel@tonic-gate * but for now this will be good 36947c478bd9Sstevel@tonic-gate * enough. Callers of this routine are 36957c478bd9Sstevel@tonic-gate * currently insulated from the state stuff. 36967c478bd9Sstevel@tonic-gate */ 3697d216dff5SRobert Mastors rfs4_update_lease(sp->rs_owner->ro_client); 36987c478bd9Sstevel@tonic-gate 36997c478bd9Sstevel@tonic-gate /* 37007c478bd9Sstevel@tonic-gate * If a delegation is present on this file and 37017c478bd9Sstevel@tonic-gate * this is a WRITE, then update the lastwrite 37027c478bd9Sstevel@tonic-gate * time to indicate that activity is present. 37037c478bd9Sstevel@tonic-gate */ 3704d216dff5SRobert Mastors if (sp->rs_finfo->rf_dinfo.rd_dtype == 3705d216dff5SRobert Mastors OPEN_DELEGATE_WRITE && 37067c478bd9Sstevel@tonic-gate mode == FWRITE) { 3707d216dff5SRobert Mastors sp->rs_finfo->rf_dinfo.rd_time_lastwrite = 37087c478bd9Sstevel@tonic-gate gethrestime_sec(); 37097c478bd9Sstevel@tonic-gate } 37107c478bd9Sstevel@tonic-gate 37117c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 37127c478bd9Sstevel@tonic-gate 37137c478bd9Sstevel@tonic-gate return (stat); 37147c478bd9Sstevel@tonic-gate } 37157c478bd9Sstevel@tonic-gate 37167c478bd9Sstevel@tonic-gate if (dsp != NULL) { 37177c478bd9Sstevel@tonic-gate /* Is associated server instance in its grace period? */ 3718d216dff5SRobert Mastors if (rfs4_clnt_in_grace(dsp->rds_client)) { 37197c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(dsp); 37207c478bd9Sstevel@tonic-gate return (NFS4ERR_GRACE); 37217c478bd9Sstevel@tonic-gate } 3722d216dff5SRobert Mastors if (dsp->rds_delegid.bits.chgseq != id->bits.chgseq) { 37237c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(dsp); 37247c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 37257c478bd9Sstevel@tonic-gate } 37267c478bd9Sstevel@tonic-gate 37277c478bd9Sstevel@tonic-gate /* Ensure specified filehandle matches */ 3728d216dff5SRobert Mastors if (dsp->rds_finfo->rf_vp != vp) { 37297c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(dsp); 37307c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 37317c478bd9Sstevel@tonic-gate } 37327c478bd9Sstevel@tonic-gate /* 37337c478bd9Sstevel@tonic-gate * Return whether this state has write 37347c478bd9Sstevel@tonic-gate * delegation if desired 37357c478bd9Sstevel@tonic-gate */ 3736d216dff5SRobert Mastors if (deleg && (dsp->rds_finfo->rf_dinfo.rd_dtype == 3737d216dff5SRobert Mastors OPEN_DELEGATE_WRITE)) 37387c478bd9Sstevel@tonic-gate *deleg = TRUE; 37397c478bd9Sstevel@tonic-gate 3740d216dff5SRobert Mastors rfs4_update_lease(dsp->rds_client); 37417c478bd9Sstevel@tonic-gate 37427c478bd9Sstevel@tonic-gate /* 37437c478bd9Sstevel@tonic-gate * If a delegation is present on this file and 37447c478bd9Sstevel@tonic-gate * this is a WRITE, then update the lastwrite 37457c478bd9Sstevel@tonic-gate * time to indicate that activity is present. 37467c478bd9Sstevel@tonic-gate */ 3747d216dff5SRobert Mastors if (dsp->rds_finfo->rf_dinfo.rd_dtype == 3748d216dff5SRobert Mastors OPEN_DELEGATE_WRITE && mode == FWRITE) { 3749d216dff5SRobert Mastors dsp->rds_finfo->rf_dinfo.rd_time_lastwrite = 37507c478bd9Sstevel@tonic-gate gethrestime_sec(); 37517c478bd9Sstevel@tonic-gate } 37527c478bd9Sstevel@tonic-gate 37537c478bd9Sstevel@tonic-gate /* 37547c478bd9Sstevel@tonic-gate * XXX - what happens if this is a WRITE and the 37557c478bd9Sstevel@tonic-gate * delegation type of for READ. 37567c478bd9Sstevel@tonic-gate */ 37577c478bd9Sstevel@tonic-gate rfs4_deleg_state_rele(dsp); 37587c478bd9Sstevel@tonic-gate 37597c478bd9Sstevel@tonic-gate return (stat); 37607c478bd9Sstevel@tonic-gate } 37617c478bd9Sstevel@tonic-gate /* 37627c478bd9Sstevel@tonic-gate * If we got this far, something bad happened 37637c478bd9Sstevel@tonic-gate */ 37647c478bd9Sstevel@tonic-gate return (NFS4ERR_BAD_STATEID); 37657c478bd9Sstevel@tonic-gate } 37667c478bd9Sstevel@tonic-gate } 37677c478bd9Sstevel@tonic-gate 37687c478bd9Sstevel@tonic-gate 37697c478bd9Sstevel@tonic-gate /* 37707c478bd9Sstevel@tonic-gate * This is a special function in that for the file struct provided the 37717c478bd9Sstevel@tonic-gate * server wants to remove/close all current state associated with the 37727c478bd9Sstevel@tonic-gate * file. The prime use of this would be with OP_REMOVE to force the 37737c478bd9Sstevel@tonic-gate * release of state and particularly of file locks. 37747c478bd9Sstevel@tonic-gate * 37757c478bd9Sstevel@tonic-gate * There is an assumption that there is no delegations outstanding on 37767c478bd9Sstevel@tonic-gate * this file at this point. The caller should have waited for those 37777c478bd9Sstevel@tonic-gate * to be returned or revoked. 37787c478bd9Sstevel@tonic-gate */ 37797c478bd9Sstevel@tonic-gate void 37807c478bd9Sstevel@tonic-gate rfs4_close_all_state(rfs4_file_t *fp) 37817c478bd9Sstevel@tonic-gate { 37827c478bd9Sstevel@tonic-gate rfs4_state_t *sp; 37837c478bd9Sstevel@tonic-gate 3784d216dff5SRobert Mastors rfs4_dbe_lock(fp->rf_dbe); 37857c478bd9Sstevel@tonic-gate 37867c478bd9Sstevel@tonic-gate #ifdef DEBUG 37877c478bd9Sstevel@tonic-gate /* only applies when server is handing out delegations */ 37887c478bd9Sstevel@tonic-gate if (rfs4_deleg_policy != SRV_NEVER_DELEGATE) 3789d216dff5SRobert Mastors ASSERT(fp->rf_dinfo.rd_hold_grant > 0); 37907c478bd9Sstevel@tonic-gate #endif 37917c478bd9Sstevel@tonic-gate 37927c478bd9Sstevel@tonic-gate /* No delegations for this file */ 3793d216dff5SRobert Mastors ASSERT(list_is_empty(&fp->rf_delegstatelist)); 37947c478bd9Sstevel@tonic-gate 37957c478bd9Sstevel@tonic-gate /* Make sure that it can not be found */ 3796d216dff5SRobert Mastors rfs4_dbe_invalidate(fp->rf_dbe); 37977c478bd9Sstevel@tonic-gate 3798d216dff5SRobert Mastors if (fp->rf_vp == NULL) { 3799d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe); 38007c478bd9Sstevel@tonic-gate return; 38017c478bd9Sstevel@tonic-gate } 3802d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe); 38037c478bd9Sstevel@tonic-gate 38047c478bd9Sstevel@tonic-gate /* 38057c478bd9Sstevel@tonic-gate * Hold as writer to prevent other server threads from 38067c478bd9Sstevel@tonic-gate * processing requests related to the file while all state is 38077c478bd9Sstevel@tonic-gate * being removed. 38087c478bd9Sstevel@tonic-gate */ 3809d216dff5SRobert Mastors rw_enter(&fp->rf_file_rwlock, RW_WRITER); 38107c478bd9Sstevel@tonic-gate 38117c478bd9Sstevel@tonic-gate /* Remove ALL state from the file */ 38127c478bd9Sstevel@tonic-gate while (sp = rfs4_findstate_by_file(fp)) { 38137c478bd9Sstevel@tonic-gate rfs4_state_close(sp, FALSE, FALSE, CRED()); 38147c478bd9Sstevel@tonic-gate rfs4_state_rele_nounlock(sp); 38157c478bd9Sstevel@tonic-gate } 38167c478bd9Sstevel@tonic-gate 38177c478bd9Sstevel@tonic-gate /* 38187c478bd9Sstevel@tonic-gate * This is only safe since there are no further references to 38197c478bd9Sstevel@tonic-gate * the file. 38207c478bd9Sstevel@tonic-gate */ 3821d216dff5SRobert Mastors rfs4_dbe_lock(fp->rf_dbe); 3822d216dff5SRobert Mastors if (fp->rf_vp) { 3823d216dff5SRobert Mastors vnode_t *vp = fp->rf_vp; 38241b300de9Sjwahlig 3825d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock); 38261b300de9Sjwahlig (void) vsd_set(vp, nfs4_srv_vkey, NULL); 3827d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock); 38281b300de9Sjwahlig VN_RELE(vp); 3829d216dff5SRobert Mastors fp->rf_vp = NULL; 38307c478bd9Sstevel@tonic-gate } 3831d216dff5SRobert Mastors rfs4_dbe_unlock(fp->rf_dbe); 38327c478bd9Sstevel@tonic-gate 38337c478bd9Sstevel@tonic-gate /* Finally let other references to proceed */ 3834d216dff5SRobert Mastors rw_exit(&fp->rf_file_rwlock); 38357c478bd9Sstevel@tonic-gate } 38367c478bd9Sstevel@tonic-gate 38377c478bd9Sstevel@tonic-gate /* 38387c478bd9Sstevel@tonic-gate * This function is used as a target for the rfs4_dbe_walk() call 38397c478bd9Sstevel@tonic-gate * below. The purpose of this function is to see if the 38407c478bd9Sstevel@tonic-gate * lockowner_state refers to a file that resides within the exportinfo 38417c478bd9Sstevel@tonic-gate * export. If so, then remove the lock_owner state (file locks and 38427c478bd9Sstevel@tonic-gate * share "locks") for this object since the intent is the server is 38437c478bd9Sstevel@tonic-gate * unexporting the specified directory. Be sure to invalidate the 38447c478bd9Sstevel@tonic-gate * object after the state has been released 38457c478bd9Sstevel@tonic-gate */ 38467c478bd9Sstevel@tonic-gate static void 38477c478bd9Sstevel@tonic-gate rfs4_lo_state_walk_callout(rfs4_entry_t u_entry, void *e) 38487c478bd9Sstevel@tonic-gate { 38497c478bd9Sstevel@tonic-gate rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; 38507c478bd9Sstevel@tonic-gate struct exportinfo *exi = (struct exportinfo *)e; 3851b096b66cSnr123932 nfs_fh4_fmt_t fhfmt4, *exi_fhp, *finfo_fhp; 3852b096b66cSnr123932 fhandle_t *efhp; 38537c478bd9Sstevel@tonic-gate 3854b096b66cSnr123932 efhp = (fhandle_t *)&exi->exi_fh; 3855b096b66cSnr123932 exi_fhp = (nfs_fh4_fmt_t *)&fhfmt4; 3856b096b66cSnr123932 3857b096b66cSnr123932 FH_TO_FMT4(efhp, exi_fhp); 3858b096b66cSnr123932 3859d216dff5SRobert Mastors finfo_fhp = (nfs_fh4_fmt_t *)lsp->rls_state->rs_finfo-> 3860d216dff5SRobert Mastors rf_filehandle.nfs_fh4_val; 38617c478bd9Sstevel@tonic-gate 38627c478bd9Sstevel@tonic-gate if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) && 38637c478bd9Sstevel@tonic-gate bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata, 38647c478bd9Sstevel@tonic-gate exi_fhp->fh4_xlen) == 0) { 3865d216dff5SRobert Mastors rfs4_state_close(lsp->rls_state, FALSE, FALSE, CRED()); 3866d216dff5SRobert Mastors rfs4_dbe_invalidate(lsp->rls_dbe); 3867d216dff5SRobert Mastors rfs4_dbe_invalidate(lsp->rls_state->rs_dbe); 38687c478bd9Sstevel@tonic-gate } 38697c478bd9Sstevel@tonic-gate } 38707c478bd9Sstevel@tonic-gate 38717c478bd9Sstevel@tonic-gate /* 38727c478bd9Sstevel@tonic-gate * This function is used as a target for the rfs4_dbe_walk() call 38737c478bd9Sstevel@tonic-gate * below. The purpose of this function is to see if the state refers 38747c478bd9Sstevel@tonic-gate * to a file that resides within the exportinfo export. If so, then 38757c478bd9Sstevel@tonic-gate * remove the open state for this object since the intent is the 38767c478bd9Sstevel@tonic-gate * server is unexporting the specified directory. The main result for 38777c478bd9Sstevel@tonic-gate * this type of entry is to invalidate it such it will not be found in 38787c478bd9Sstevel@tonic-gate * the future. 38797c478bd9Sstevel@tonic-gate */ 38807c478bd9Sstevel@tonic-gate static void 38817c478bd9Sstevel@tonic-gate rfs4_state_walk_callout(rfs4_entry_t u_entry, void *e) 38827c478bd9Sstevel@tonic-gate { 38837c478bd9Sstevel@tonic-gate rfs4_state_t *sp = (rfs4_state_t *)u_entry; 38847c478bd9Sstevel@tonic-gate struct exportinfo *exi = (struct exportinfo *)e; 3885b096b66cSnr123932 nfs_fh4_fmt_t fhfmt4, *exi_fhp, *finfo_fhp; 3886b096b66cSnr123932 fhandle_t *efhp; 38877c478bd9Sstevel@tonic-gate 3888b096b66cSnr123932 efhp = (fhandle_t *)&exi->exi_fh; 3889b096b66cSnr123932 exi_fhp = (nfs_fh4_fmt_t *)&fhfmt4; 3890b096b66cSnr123932 3891b096b66cSnr123932 FH_TO_FMT4(efhp, exi_fhp); 3892b096b66cSnr123932 38937c478bd9Sstevel@tonic-gate finfo_fhp = 3894d216dff5SRobert Mastors (nfs_fh4_fmt_t *)sp->rs_finfo->rf_filehandle.nfs_fh4_val; 38957c478bd9Sstevel@tonic-gate 38967c478bd9Sstevel@tonic-gate if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) && 38977c478bd9Sstevel@tonic-gate bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata, 38987c478bd9Sstevel@tonic-gate exi_fhp->fh4_xlen) == 0) { 38997c478bd9Sstevel@tonic-gate rfs4_state_close(sp, TRUE, FALSE, CRED()); 3900d216dff5SRobert Mastors rfs4_dbe_invalidate(sp->rs_dbe); 39017c478bd9Sstevel@tonic-gate } 39027c478bd9Sstevel@tonic-gate } 39037c478bd9Sstevel@tonic-gate 39047c478bd9Sstevel@tonic-gate /* 39057c478bd9Sstevel@tonic-gate * This function is used as a target for the rfs4_dbe_walk() call 39067c478bd9Sstevel@tonic-gate * below. The purpose of this function is to see if the state refers 39077c478bd9Sstevel@tonic-gate * to a file that resides within the exportinfo export. If so, then 39087c478bd9Sstevel@tonic-gate * remove the deleg state for this object since the intent is the 39097c478bd9Sstevel@tonic-gate * server is unexporting the specified directory. The main result for 39107c478bd9Sstevel@tonic-gate * this type of entry is to invalidate it such it will not be found in 39117c478bd9Sstevel@tonic-gate * the future. 39127c478bd9Sstevel@tonic-gate */ 39137c478bd9Sstevel@tonic-gate static void 39147c478bd9Sstevel@tonic-gate rfs4_deleg_state_walk_callout(rfs4_entry_t u_entry, void *e) 39157c478bd9Sstevel@tonic-gate { 39167c478bd9Sstevel@tonic-gate rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; 39177c478bd9Sstevel@tonic-gate struct exportinfo *exi = (struct exportinfo *)e; 3918b096b66cSnr123932 nfs_fh4_fmt_t fhfmt4, *exi_fhp, *finfo_fhp; 3919b096b66cSnr123932 fhandle_t *efhp; 39207c478bd9Sstevel@tonic-gate 3921b096b66cSnr123932 efhp = (fhandle_t *)&exi->exi_fh; 3922b096b66cSnr123932 exi_fhp = (nfs_fh4_fmt_t *)&fhfmt4; 3923b096b66cSnr123932 3924b096b66cSnr123932 FH_TO_FMT4(efhp, exi_fhp); 3925b096b66cSnr123932 39267c478bd9Sstevel@tonic-gate finfo_fhp = 3927d216dff5SRobert Mastors (nfs_fh4_fmt_t *)dsp->rds_finfo->rf_filehandle.nfs_fh4_val; 39287c478bd9Sstevel@tonic-gate 39297c478bd9Sstevel@tonic-gate if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) && 39307c478bd9Sstevel@tonic-gate bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata, 39317c478bd9Sstevel@tonic-gate exi_fhp->fh4_xlen) == 0) { 3932d216dff5SRobert Mastors rfs4_dbe_invalidate(dsp->rds_dbe); 39337c478bd9Sstevel@tonic-gate } 39347c478bd9Sstevel@tonic-gate } 39357c478bd9Sstevel@tonic-gate 39367c478bd9Sstevel@tonic-gate /* 39377c478bd9Sstevel@tonic-gate * This function is used as a target for the rfs4_dbe_walk() call 39387c478bd9Sstevel@tonic-gate * below. The purpose of this function is to see if the state refers 39397c478bd9Sstevel@tonic-gate * to a file that resides within the exportinfo export. If so, then 39407c478bd9Sstevel@tonic-gate * release vnode hold for this object since the intent is the server 39417c478bd9Sstevel@tonic-gate * is unexporting the specified directory. Invalidation will prevent 39427c478bd9Sstevel@tonic-gate * this struct from being found in the future. 39437c478bd9Sstevel@tonic-gate */ 39447c478bd9Sstevel@tonic-gate static void 39457c478bd9Sstevel@tonic-gate rfs4_file_walk_callout(rfs4_entry_t u_entry, void *e) 39467c478bd9Sstevel@tonic-gate { 39477c478bd9Sstevel@tonic-gate rfs4_file_t *fp = (rfs4_file_t *)u_entry; 39487c478bd9Sstevel@tonic-gate struct exportinfo *exi = (struct exportinfo *)e; 3949b096b66cSnr123932 nfs_fh4_fmt_t fhfmt4, *exi_fhp, *finfo_fhp; 3950b096b66cSnr123932 fhandle_t *efhp; 39517c478bd9Sstevel@tonic-gate 3952b096b66cSnr123932 efhp = (fhandle_t *)&exi->exi_fh; 3953b096b66cSnr123932 exi_fhp = (nfs_fh4_fmt_t *)&fhfmt4; 3954b096b66cSnr123932 3955b096b66cSnr123932 FH_TO_FMT4(efhp, exi_fhp); 3956b096b66cSnr123932 3957d216dff5SRobert Mastors finfo_fhp = (nfs_fh4_fmt_t *)fp->rf_filehandle.nfs_fh4_val; 39587c478bd9Sstevel@tonic-gate 39597c478bd9Sstevel@tonic-gate if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) && 39607c478bd9Sstevel@tonic-gate bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata, 39617c478bd9Sstevel@tonic-gate exi_fhp->fh4_xlen) == 0) { 3962d216dff5SRobert Mastors if (fp->rf_vp) { 3963d216dff5SRobert Mastors vnode_t *vp = fp->rf_vp; 3964bb972d76Sjwahlig 3965da6c28aaSamw /* 3966da6c28aaSamw * don't leak monitors and remove the reference 3967da6c28aaSamw * put on the vnode when the delegation was granted. 3968da6c28aaSamw */ 3969d216dff5SRobert Mastors if (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_READ) { 3970bb972d76Sjwahlig (void) fem_uninstall(vp, deleg_rdops, 39717c478bd9Sstevel@tonic-gate (void *)fp); 3972da6c28aaSamw vn_open_downgrade(vp, FREAD); 3973d216dff5SRobert Mastors } else if (fp->rf_dinfo.rd_dtype == 3974d216dff5SRobert Mastors OPEN_DELEGATE_WRITE) { 3975bb972d76Sjwahlig (void) fem_uninstall(vp, deleg_wrops, 39767c478bd9Sstevel@tonic-gate (void *)fp); 3977da6c28aaSamw vn_open_downgrade(vp, FREAD|FWRITE); 3978da6c28aaSamw } 3979d216dff5SRobert Mastors mutex_enter(&vp->v_vsd_lock); 3980bb972d76Sjwahlig (void) vsd_set(vp, nfs4_srv_vkey, NULL); 3981d216dff5SRobert Mastors mutex_exit(&vp->v_vsd_lock); 3982bb972d76Sjwahlig VN_RELE(vp); 3983d216dff5SRobert Mastors fp->rf_vp = NULL; 39847c478bd9Sstevel@tonic-gate } 3985d216dff5SRobert Mastors rfs4_dbe_invalidate(fp->rf_dbe); 39867c478bd9Sstevel@tonic-gate } 39877c478bd9Sstevel@tonic-gate } 39887c478bd9Sstevel@tonic-gate 39897c478bd9Sstevel@tonic-gate /* 39907c478bd9Sstevel@tonic-gate * Given a directory that is being unexported, cleanup/release all 39917c478bd9Sstevel@tonic-gate * state in the server that refers to objects residing underneath this 39927c478bd9Sstevel@tonic-gate * particular export. The ordering of the release is important. 39937c478bd9Sstevel@tonic-gate * Lock_owner, then state and then file. 39947c478bd9Sstevel@tonic-gate */ 39957c478bd9Sstevel@tonic-gate void 39967c478bd9Sstevel@tonic-gate rfs4_clean_state_exi(struct exportinfo *exi) 39977c478bd9Sstevel@tonic-gate { 39987c478bd9Sstevel@tonic-gate mutex_enter(&rfs4_state_lock); 39997c478bd9Sstevel@tonic-gate 40007c478bd9Sstevel@tonic-gate if (rfs4_server_state == NULL) { 40017c478bd9Sstevel@tonic-gate mutex_exit(&rfs4_state_lock); 40027c478bd9Sstevel@tonic-gate return; 40037c478bd9Sstevel@tonic-gate } 40047c478bd9Sstevel@tonic-gate 40057c478bd9Sstevel@tonic-gate rfs4_dbe_walk(rfs4_lo_state_tab, rfs4_lo_state_walk_callout, exi); 40067c478bd9Sstevel@tonic-gate rfs4_dbe_walk(rfs4_state_tab, rfs4_state_walk_callout, exi); 40077c478bd9Sstevel@tonic-gate rfs4_dbe_walk(rfs4_deleg_state_tab, rfs4_deleg_state_walk_callout, exi); 40087c478bd9Sstevel@tonic-gate rfs4_dbe_walk(rfs4_file_tab, rfs4_file_walk_callout, exi); 40097c478bd9Sstevel@tonic-gate 40107c478bd9Sstevel@tonic-gate mutex_exit(&rfs4_state_lock); 40117c478bd9Sstevel@tonic-gate } 4012