Home | History | Annotate | Download | only in nfs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  *	Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  *	Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
     27 /*	  All Rights Reserved  	*/
     28 
     29 #ifndef	_NFS_RNODE4_H
     30 #define	_NFS_RNODE4_H
     31 
     32 #ifdef	__cplusplus
     33 extern "C" {
     34 #endif
     35 
     36 #include <nfs/rnode.h>		/* for symlink_cache, nfs_rwlock_t, etc. */
     37 #include <nfs/nfs4.h>
     38 #include <nfs/nfs4_clnt.h>
     39 #include <nfs/nfs4_pnfs.h>
     40 #include <sys/thread.h>
     41 #include <sys/sysmacros.h>	/* for offsetof */
     42 
     43 typedef enum nfs4_stub_type {
     44 	NFS4_STUB_NONE,
     45 	NFS4_STUB_MIRRORMOUNT
     46 } nfs4_stub_type_t;
     47 
     48 typedef enum nfs4_access_type {
     49 	NFS4_ACCESS_UNKNOWN,
     50 	NFS4_ACCESS_ALLOWED,
     51 	NFS4_ACCESS_DENIED
     52 } nfs4_access_type_t;
     53 
     54 /*
     55  * Access cache
     56  */
     57 typedef struct acache4_hash {
     58 	struct acache4 *next;
     59 	struct acache4 *prev;
     60 	krwlock_t lock;
     61 } acache4_hash_t;
     62 
     63 typedef struct acache4 {
     64 	struct acache4 *next;	/* next and prev must be first */
     65 	struct acache4 *prev;
     66 	uint32_t known;
     67 	uint32_t allowed;
     68 	struct rnode4 *rnode;
     69 	cred_t *cred;
     70 	struct acache4 *list;
     71 	struct acache4_hash *hashq;
     72 } acache4_t;
     73 
     74 /*
     75  * The various values for the commit states.  These are stored in
     76  * the p_fsdata byte in the page struct.
     77  * Unlike in the nfsv3 client, these values are bit fields.
     78  */
     79 #define	C_NOCOMMIT4	0x0	/* no commit is required */
     80 #define	C_COMMIT4	0x1	/* a commit is required */
     81 #define	C_DELAY4	0x2	/* a commit can be delayed */
     82 #define	C_ERROR4	0x4	/* an error occurred during a commit */
     83 
     84 #define	C_DELAYCOMMIT4	(C_COMMIT4 | C_DELAY4)
     85 
     86 /*
     87  * Note on the different buffer sizes in rddir4_cache:
     88  * There seems to be some discrepancy between the intended and actual
     89  * use of entlen and buflen, which does not correspond to the comment below.
     90  *	entlen - nfsv2/3 used as both alloc'd size of entries buffer and
     91  *		as the actual size of the entries (XXX is this correct?).
     92  *		nfsv4 will use it only as the alloc'd size.
     93  *	buflen - used for calculations of readahead.
     94  *	actlen - added for nfsv4 to serve as the size of the useful
     95  *		portion of the entries buffer. That is because in
     96  *		nfsv4, the otw entries are converted to system entries,
     97  *		and may not be the same size - thus buffer may not be full.
     98  */
     99 typedef struct rddir4_cache {
    100 	lloff_t _cookie;	/* cookie used to find this cache entry */
    101 	lloff_t _ncookie;	/* cookie used to find the next cache entry */
    102 	char *entries;		/* buffer containing dirent entries */
    103 	int eof;		/* EOF reached after this request */
    104 	int entlen;		/* size of dirent entries in buf */
    105 	int buflen;		/* size of the buffer used to store entries */
    106 	int actlen;		/* size of the actual entries (nfsv4 only) */
    107 	int flags;		/* control flags, see below */
    108 	kcondvar_t cv;		/* cv for blocking */
    109 	int error;		/* error from RPC operation */
    110 	void *data;		/* private data */
    111 } rddir4_cache;
    112 
    113 #define	nfs4_cookie	_cookie._f
    114 #define	nfs4_ncookie	_ncookie._f
    115 
    116 /*
    117  * Shadow vnode, v4 only.
    118  *
    119  * A file's shadow vnode list is protected by its hash bucket lock,
    120  * r_hashq->r_lock.
    121  *
    122  * sv_r_vnode is protected by the appropriate vnode locks.
    123  *
    124  * sv_dfh, sv_name, sv_dfileid, and sv_dfileid_valid are protected
    125  * by rp->r_svlock.
    126  */
    127 
    128 typedef struct insq_link {
    129 	void	*forw;
    130 	void	*back;
    131 } insq_link_t;
    132 
    133 typedef struct svnode {
    134 	insq_link_t	sv_link;	/* must be first for insque */
    135 	vnode_t		*sv_r_vnode;	/* vnode for this shadow */
    136 	nfs4_fname_t	*sv_name;	/* component name */
    137 	nfs4_sharedfh_t	*sv_dfh;	/* directory file handle */
    138 } svnode_t;
    139 
    140 #define	sv_forw			sv_link.forw
    141 #define	sv_back			sv_link.back
    142 extern svnode_t			*vtosv(vnode_t *);
    143 #define	VTOSV(vp)		vtosv(vp)
    144 #define	SVTOV(svp)		(((svp)->sv_r_vnode))
    145 #define	IS_SHADOW(vp, rp)	((vp) != (rp)->r_vnode)
    146 
    147 /*
    148  * The format of the hash bucket used to lookup rnodes from a file handle.
    149  */
    150 typedef struct r4hashq {
    151 	struct rnode4 *r_hashf;
    152 	struct rnode4 *r_hashb;
    153 	krwlock_t r_lock;
    154 } r4hashq_t;
    155 
    156 /*
    157  * Remote file information structure.
    158  *
    159  * The rnode is the "inode" for remote files.  It contains all the
    160  * information necessary to handle remote file on the client side.
    161  *
    162  * Note on file sizes:  we keep two file sizes in the rnode: the size
    163  * according to the client (r_size) and the size according to the server
    164  * (r_attr.va_size).  They can differ because we modify r_size during a
    165  * write system call (nfs_rdwr), before the write request goes over the
    166  * wire (before the file is actually modified on the server).  If an OTW
    167  * request occurs before the cached data is written to the server the file
    168  * size returned from the server (r_attr.va_size) may not match r_size.
    169  * r_size is the one we use, in general.  r_attr.va_size is only used to
    170  * determine whether or not our cached data is valid.
    171  *
    172  * Each rnode has 5 locks associated with it (not including the rnode
    173  * hash table and free list locks):
    174  *
    175  *	r_rwlock:	Serializes nfs_write and nfs_setattr requests
    176  *			and allows nfs_read requests to proceed in parallel.
    177  *			Serializes reads/updates to directories.
    178  *
    179  *	r_lkserlock:	Serializes lock requests with map, write, and
    180  *			readahead operations.
    181  *
    182  *	r_statelock:	Protects all fields in the rnode except for
    183  *			those listed below.  This lock is intented
    184  *			to be held for relatively short periods of
    185  *			time (not accross entire putpage operations,
    186  *			for example).
    187  *
    188  *	r_statev4_lock:	Protects the created_v4 flag, the lock_owners list,
    189  *			and all the delegation fields except r_deleg_list.
    190  *
    191  *	r_os_lock:	Protects r_open_streams.
    192  *
    193  *	r_lo_lock;	Protects the layout list.
    194  *
    195  *
    196  * The following members are protected by the mutex rp4freelist_lock:
    197  *	r_freef
    198  *	r_freeb
    199  *
    200  * The following members are protected by the hash bucket rwlock:
    201  *	r_hashf
    202  *	r_hashb
    203  *
    204  * r_fh is read-only except when an rnode is created (or recycled from the
    205  * free list).
    206  *
    207  * The following members are protected by nfs4_server_t::s_lock:
    208  *	r_deleg_list
    209  *
    210  * Note: r_modaddr is only accessed when the r_statelock mutex is held.
    211  *	Its value is also controlled via r_rwlock.  It is assumed that
    212  *	there will be only 1 writer active at a time, so it safe to
    213  *	set r_modaddr and release r_statelock as long as the r_rwlock
    214  *	writer lock is held.
    215  *
    216  * r_inmap informs nfs4_read()/write() that there is a call to nfs4_map()
    217  * in progress. nfs4_read()/write() check r_inmap to decide whether
    218  * to perform directio on the file or not. r_inmap is atomically
    219  * incremented in nfs4_map() before the address space routines are
    220  * called and atomically decremented just before nfs4_map() exits.
    221  * r_inmap is not protected by any lock.
    222  *
    223  * r_mapcnt tells that the rnode has mapped pages. r_inmap can be 0
    224  * while the rnode has mapped pages.
    225  *
    226  * 64-bit offsets: the code formerly assumed that atomic reads of
    227  * r_size were safe and reliable; on 32-bit architectures, this is
    228  * not true since an intervening bus cycle from another processor
    229  * could update half of the size field.  The r_statelock must now
    230  * be held whenever any kind of access of r_size is made.
    231  *
    232  * Lock ordering:
    233  * 	r_rwlock > r_lkserlock > r_os_lock > r_statelock > r_statev4_lock
    234  *	vnode_t::v_lock > r_os_lock
    235  */
    236 struct exportinfo;	/* defined in nfs/export.h */
    237 struct servinfo4;	/* defined in nfs/nfs4_clnt.h */
    238 struct failinfo;	/* defined in nfs/nfs_clnt.h */
    239 struct mntinfo4;	/* defined in nfs/nfs4_clnt.h */
    240 
    241 typedef struct rnode4 {
    242 	/* the hash fields must be first to match the rhashq_t */
    243 	struct rnode4	*r_hashf;	/* hash queue forward pointer */
    244 	struct rnode4	*r_hashb;	/* hash queue back pointer */
    245 	struct rnode4	*r_freef;	/* free list forward pointer */
    246 	struct rnode4	*r_freeb;	/* free list back pointer */
    247 	r4hashq_t	*r_hashq;	/* pointer to the hash bucket */
    248 
    249 	svnode_t	r_svnode;	/* "master" shadow vnode for file */
    250 	kmutex_t	r_svlock;	/* serializes access to svnode list */
    251 	nfs_rwlock_t	r_rwlock;	/* serializes write/setattr requests */
    252 	nfs_rwlock_t	r_lkserlock;	/* serialize lock with other ops */
    253 	kmutex_t	r_statelock;	/* protects (most of) rnode contents */
    254 	nfs4_sharedfh_t	*r_fh;		/* file handle */
    255 	struct servinfo4
    256 			*r_server;	/* current server */
    257 	u_offset_t	r_nextr;	/* next byte read offset (read-ahead) */
    258 	uint_t		r_flags;	/* flags, see below */
    259 	short		r_error;	/* async write error */
    260 	cred_t		*r_unlcred;	/* unlinked credentials */
    261 	char		*r_unlname;	/* unlinked file name */
    262 	vnode_t		*r_unldvp;	/* parent dir of unlinked file */
    263 	vnode_t		*r_xattr_dir;	/* cached xattr dir vnode */
    264 	len_t		r_size;		/* client's view of file size */
    265 	vattr_t		r_attr;		/* cached vnode attributes */
    266 	hrtime_t	r_time_attr_saved; /* time attributes were cached */
    267 	hrtime_t	r_time_attr_inval; /* time attributes become invalid */
    268 	hrtime_t	r_time_cache_inval; /* time caches become invalid */
    269 	time_t		r_delay_wait;	/* future time for DELAY handling */
    270 	int		r_delay_interval; /* Number of Secs of last DELAY */
    271 	time_t		r_last_recov;	/* time of last recovery operation */
    272 	nfs4_recov_t	r_recov_act;	/* action from last recovery op */
    273 	long		r_mapcnt;	/* count of mmapped pages */
    274 	uint_t		r_count;	/* # of refs not reflect in v_count */
    275 	uint_t		r_awcount;	/* # of outstanding async write */
    276 	uint_t		r_gcount;	/* getattrs waiting to flush pages */
    277 	kcondvar_t	r_cv;		/* condvar for blocked threads */
    278 	int		(*r_putapage)	/* address of putapage routine */
    279 		(vnode_t *, page_t *, u_offset_t *, size_t *, int, cred_t *);
    280 	void		*r_dir;		/* cache of readdir responses */
    281 	rddir4_cache	*r_direof;	/* pointer to the EOF entry */
    282 	symlink_cache	r_symlink;	/* cached readlink response */
    283 	verifier4	r_writeverf;	/* file data write verifier */
    284 	uint64_t	r_writeverfcnt;	/* write verifier transition */
    285 	u_offset_t	r_modaddr;	/* address for page in writerp */
    286 	commit_t	r_commit;	/* commit information */
    287 	u_offset_t	r_truncaddr;	/* base for truncate operation */
    288 	vsecattr_t	*r_secattr;	/* cached security attributes (acls) */
    289 	verifier4	r_cookieverf4;	/* version 4 readdir cookie verifier */
    290 	nfs4_pathconf_info_t r_pathconf; /* cached pathconf info */
    291 	acache4_t	*r_acache;	/* list of access cache entries */
    292 	list_t		r_open_streams;	/* open streams list */
    293 	kmutex_t	r_os_lock;	/* protects r_open_streams */
    294 	nfs4_lock_owner_t
    295 			r_lo_head;	/* lock owners list head */
    296 	int		created_v4;	/* 1 if file has been created in v4 */
    297 	kmutex_t	r_statev4_lock;	/* protects created_v4, state4ptr */
    298 
    299 	list_node_t	r_deleg_link;	/* linkage into list of */
    300 					/* delegated rnodes for this server */
    301 	open_delegation_type4
    302 			r_deleg_type;	/* type of delegation granted */
    303 	stateid4	r_deleg_stateid;
    304 					/* delegation state id */
    305 	nfs_space_limit4
    306 			r_deleg_limit;	/* file limits returned from */
    307 					/* server on delegated open */
    308 	nfsace4		r_deleg_perms;	/* file permissions returned from */
    309 					/* server on delegated open */
    310 	fattr4_change	r_deleg_change;	/* current deleg change attr */
    311 	fattr4_change	r_deleg_change_grant;
    312 					/* change @ write deleg grant */
    313 	cred_t		*r_deleg_cred;	/* credential in force when the */
    314 					/* delegation was granted */
    315 	open_delegation_type4
    316 			r_deleg_needs_recovery;
    317 					/* delegation needs recovery */
    318 					/* This contains the delegation type */
    319 					/* for use with CLAIM_PREVIOUS. */
    320 					/* OPEN_DELEGATE_NONE means recovery */
    321 					/* is not needed. */
    322 	unsigned	r_deleg_needs_recall:1;
    323 					/* delegation has been recalled by */
    324 					/* the server during open with */
    325 					/* CLAIM_PREVIOUS */
    326 	unsigned 	r_deleg_return_pending:1;
    327 					/* delegreturn is pending, don't use */
    328 					/* the delegation stateid, set in */
    329 					/* nfs4_dlistadd */
    330 	unsigned 	r_deleg_return_inprog:1;
    331 					/* delegreturn is in progress, may */
    332 					/* only be set by nfs4delegreturn. */
    333 	nfs_rwlock_t    r_deleg_recall_lock;
    334 					/* lock for synchronizing delegreturn */
    335 					/* with in other operations, acquired */
    336 					/* in read mode by nfs4_start_fop, */
    337 					/* acquired in write mode in */
    338 					/* nfs4delegreturn */
    339 	fattr4_change	r_change;	/* GETATTR4 change attr;  client  */
    340 					/* should always request change   */
    341 					/* when c/mtime requested to keep */
    342 					/* change and c/mtime in sync	  */
    343 	fattr4_fileid	r_mntd_fid;	/* mounted on fileid attr	  */
    344 	kthread_t	*r_serial;	/* attrcache validation thread */
    345 	kthread_t	*r_pgflush;	/* thread flushing page cache */
    346 	list_t		r_indelmap;	/* list of delmap callers */
    347 	fattr4_fsid	r_srv_fsid;	/* fsid of srv fs containing object */
    348 					/* when rnode created; compare with */
    349 					/* sv_fsid (servinfo4_t) to see why */
    350 					/* stub type was set		    */
    351 	nfs4_stub_type_t	r_stub_type;
    352 					/* e.g. mirror-mount */
    353 	uint_t		r_inmap;	/* to serialize read/write and mmap */
    354 	kmutex_t	r_lo_lock;	/* Layout List Lock */
    355 	list_t 		r_layout;	/* pNFS layout(s) */
    356 	uint64_t	r_proxyio_count; /* Counter for proxy I/O */
    357 	uint64_t	r_dsio_count; 	/* Counter for DS I/O */
    358 	uint64_t	r_activefinds;	/* pnfs_find_layouts active on rnode */
    359 	stateid4	r_lostateid;	/* layout stateid */
    360 	kcondvar_t	r_lowait;	/* Wait For Layout */
    361 	clock_t		r_last_layoutget; /* time of last layoutget attempt */
    362 	offset4		r_last_write_offset; /* used in LAYOUTCOMMIT */
    363 	avl_node_t	r_avl;		/* layout avl tree */
    364 	nfs4_fsidlt_t	*r_fsidlt;	/* fsidlt this rnode is in */
    365 } rnode4_t;
    366 
    367 #define	r_vnode	r_svnode.sv_r_vnode
    368 
    369 /*
    370  * Flags
    371  */
    372 #define	R4READDIRWATTR	0x1	/* Use READDIR with attributes */
    373 #define	R4DIRTY		0x2	/* dirty pages from write operation */
    374 #define	R4STALE		0x4	/* stale, don't even attempt to write */
    375 #define	R4MODINPROGRESS	0x8	/* page modification happening */
    376 #define	R4TRUNCATE	0x10	/* truncating, don't commit */
    377 #define	R4HAVEVERF	0x20	/* have a write verifier to compare against */
    378 #define	R4COMMIT	0x40	/* commit in progress */
    379 #define	R4COMMITWAIT	0x80	/* someone is waiting to do a commit */
    380 #define	R4HASHED	0x100	/* rnode is in hash queues */
    381 #define	R4OUTOFSPACE	0x200	/* an out of space error has happened */
    382 #define	R4LODANGLERS	0x400	/* rnode has dangling lock_owners to cleanup */
    383 #define	R4WRITEMODIFIED	0x800	/* file data has been modified by write */
    384 #define	R4DIRECTIO	0x1000	/* bypass the buffer cache */
    385 #define	R4RECOVERR	0x2000	/* couldn't recover */
    386 #define	R4RECEXPFH	0x4000	/* recovering expired filehandle */
    387 #define	R4RECOVERRP	0x8000	/* R4RECOVERR pending, but not set (yet) */
    388 #define	R4ISXATTR	0x20000	/* rnode is a named attribute */
    389 #define	R4DELMAPLIST	0x40000	/* delmap callers tracked for as callback */
    390 #define	R4PGFLUSH	0x80000	/* page flush thread active */
    391 #define	R4INCACHEPURGE	0x100000 /* purging caches due to file size change */
    392 #define	R4LOOKUP	0x200000 /* a lookup has been done in the directory */
    393 #define	R4LAYOUTVALID	0x400000 /* a pNFS layout is available */
    394 #define	R4LASTBYTE	0x800000 /* pNFS last_write_offset is valid */
    395 #define	R4LAYOUTUNAVAIL 0x1000000 /* to be moved to pnfs_layout later */
    396 #define	R4OTWLO		0x2000000 /* OTW Layout Op In Progress */
    397 
    398 /*
    399  * Convert between vnode and rnode
    400  */
    401 #define	RTOV4(rp)	((rp)->r_vnode)
    402 #define	VTOR4(vp)	((rnode4_t *)((vp)->v_data))
    403 
    404 #define	RP_ISSTUB(rp)	(((rp)->r_stub_type != NFS4_STUB_NONE))
    405 #define	RP_ISSTUB_MIRRORMOUNT(rp) ((rp)->r_stub_type == NFS4_STUB_MIRRORMOUNT)
    406 
    407 /*
    408  * Open file instances.
    409  */
    410 
    411 typedef struct nfs4_opinst {
    412 	struct nfs4_opinst	*re_next; /* next in list */
    413 	vnode_t			*re_vp;	/* held reference */
    414 	uint32_t		re_numosp; /* number of valid open streams */
    415 	nfs4_open_stream_t	**re_osp; /* held reference */
    416 } nfs4_opinst_t;
    417 
    418 #ifdef _KERNEL
    419 
    420 extern long nrnode;
    421 
    422 /* Used for r_delay_interval */
    423 #define	NFS4_INITIAL_DELAY_INTERVAL	 1
    424 #define	NFS4_MAX_DELAY_INTERVAL		20
    425 
    426 extern rnode4_t	*r4find(r4hashq_t *, nfs4_sharedfh_t *, struct vfs *);
    427 extern rnode4_t	*r4find_unlocked(nfs4_sharedfh_t *, struct vfs *);
    428 extern void	r4flush(struct vfs *, cred_t *);
    429 extern void	destroy_rtable4(struct vfs *, cred_t *);
    430 extern int	check_rtable4(struct vfs *);
    431 extern void	rp4_addfree(rnode4_t *, cred_t *);
    432 extern void	rp4_addhash(rnode4_t *);
    433 extern void	rp4_rmhash(rnode4_t *);
    434 extern void	rp4_rmhash_locked(rnode4_t *);
    435 extern int	rtable4hash(nfs4_sharedfh_t *);
    436 
    437 extern vnode_t *makenfs4node(nfs4_sharedfh_t *, nfs4_ga_res_t *, struct vfs *,
    438 				hrtime_t, cred_t *, vnode_t *, nfs4_fname_t *);
    439 extern vnode_t *makenfs4node_by_fh(nfs4_sharedfh_t *, nfs4_sharedfh_t *,
    440     nfs4_fname_t **, nfs4_ga_res_t *, mntinfo4_t *, cred_t *, hrtime_t);
    441 
    442 extern nfs4_opinst_t *r4mkopenlist(struct mntinfo4 *);
    443 extern void	r4releopenlist(nfs4_opinst_t *);
    444 
    445 /* Access cache calls */
    446 extern nfs4_access_type_t nfs4_access_check(rnode4_t *, uint32_t, cred_t *);
    447 extern void	nfs4_access_cache(rnode4_t *rp, uint32_t, uint32_t, cred_t *);
    448 extern int	nfs4_access_purge_rp(rnode4_t *);
    449 
    450 extern int	nfs4_free_data_reclaim(rnode4_t *);
    451 extern void	nfs4_rnode_invalidate(struct vfs *);
    452 
    453 extern time_t	r2lease_time(rnode4_t *);
    454 extern int	nfs4_directio(vnode_t *, int, cred_t *);
    455 
    456 /* shadow vnode functions */
    457 extern void	sv_activate(vnode_t **, vnode_t *, nfs4_fname_t **, int);
    458 extern vnode_t	*sv_find(vnode_t *, vnode_t *, nfs4_fname_t **);
    459 extern void	sv_update_path(vnode_t *, char *, char *);
    460 extern void	sv_inactive(vnode_t *);
    461 extern void	sv_exchange(vnode_t **);
    462 extern void	sv_uninit(svnode_t *);
    463 extern void	nfs4_clear_open_streams(rnode4_t *);
    464 
    465 /*
    466  * Mark cached attributes as timed out
    467  *
    468  * The caller must not be holding the rnode r_statelock mutex.
    469  */
    470 #define	PURGE_ATTRCACHE4_LOCKED(rp)				\
    471 	rp->r_time_attr_inval = gethrtime();			\
    472 	rp->r_time_attr_saved = rp->r_time_attr_inval;		\
    473 	rp->r_pathconf.pc4_xattr_valid = 0;			\
    474 	rp->r_pathconf.pc4_cache_valid = 0;
    475 
    476 #define	PURGE_ATTRCACHE4(vp)	{				\
    477 	rnode4_t *rp = VTOR4(vp);				\
    478 	mutex_enter(&rp->r_statelock);				\
    479 	PURGE_ATTRCACHE4_LOCKED(rp);				\
    480 	mutex_exit(&rp->r_statelock);				\
    481 }
    482 
    483 
    484 extern void	nfs4_async_readdir(vnode_t *, rddir4_cache *,
    485 			cred_t *, int (*)(vnode_t *, rddir4_cache *, cred_t *));
    486 extern char	*rnode4info(rnode4_t *rp);
    487 
    488 extern int	writerp4(rnode4_t *, caddr_t, int, struct uio *, int);
    489 extern void	nfs4_set_nonvattrs(rnode4_t *, struct nfs4attr_to_vattr *);
    490 extern void	nfs4delegabandon(rnode4_t *);
    491 extern stateid4 nfs4_get_w_stateid(cred_t *, rnode4_t *, pid_t, mntinfo4_t *,
    492 		nfs_opnum4, nfs4_stateid_types_t *, int flags);
    493 extern stateid4 nfs4_get_stateid(cred_t *, rnode4_t *, pid_t, mntinfo4_t *,
    494 			nfs_opnum4, nfs4_stateid_types_t *, bool_t);
    495 extern nfsstat4 nfs4_find_or_create_lock_owner(pid_t, rnode4_t *, cred_t *,
    496 			nfs4_open_owner_t **, nfs4_open_stream_t **,
    497 			nfs4_lock_owner_t **);
    498 extern cred_t   *nfs4_get_otw_cred_by_osp(rnode4_t *, cred_t *,
    499 			nfs4_open_stream_t **, bool_t *, bool_t *);
    500 
    501 /*
    502  * Define flags for nfs4_get_w_stateid
    503  */
    504 #define	NFS4_WSID_NOPNFS	0x0	/* Get stateid for non-pnfs write */
    505 #define	NFS4_WSID_PNFS		0x1	/* Get stateid for pNFS write to DS */
    506 
    507 /*
    508  * Defines for the flag argument of nfs4delegreturn
    509  */
    510 #define	NFS4_DR_FORCE	0x1	/* discard even if start_op fails */
    511 #define	NFS4_DR_PUSH	0x2	/* push modified data back to the server */
    512 #define	NFS4_DR_DISCARD	0x4	/* discard the delegation w/o delegreturn */
    513 #define	NFS4_DR_DID_OP	0x8	/* calling function did nfs4_start_op */
    514 #define	NFS4_DR_RECALL	0x10	/* delegreturn done in response to CB_RECALL */
    515 #define	NFS4_DR_REOPEN	0x20	/* perform file reopens, if applicable */
    516 
    517 extern int nfs4delegreturn(rnode4_t *, int);
    518 extern void	nfs4_delegreturn_all(nfs4_server_t *);
    519 extern void	nfs4delegreturn_cleanup(rnode4_t *, nfs4_server_t *);
    520 extern void nfs4_delegation_accept(rnode4_t *, open_claim_type4, OPEN4res *,
    521 		nfs4_ga_res_t *, cred_t *);
    522 
    523 extern void	nfs4_dlistclean(void);
    524 extern void	nfs4_dlistadd(rnode4_t *, int);
    525 extern void	nfs4_deleg_discard(mntinfo4_t *, nfs4_server_t *);
    526 
    527 extern void	rddir4_cache_create(rnode4_t *);
    528 extern void	rddir4_cache_purge(rnode4_t *);
    529 extern void	rddir4_cache_destroy(rnode4_t *);
    530 extern rddir4_cache *rddir4_cache_lookup(rnode4_t *, offset_t, int);
    531 extern void	rddir4_cache_rele(rnode4_t *, rddir4_cache *);
    532 
    533 extern void	r4_stub_mirrormount(rnode4_t *);
    534 extern void	r4_stub_none(rnode4_t *);
    535 
    536 #ifdef DEBUG
    537 extern char	*rddir4_cache_buf_alloc(size_t, int);
    538 extern void	rddir4_cache_buf_free(void *, size_t);
    539 #endif
    540 
    541 
    542 
    543 #endif /* _KERNEL */
    544 
    545 #ifdef	__cplusplus
    546 }
    547 #endif
    548 
    549 #endif	/* _NFS_RNODE4_H */
    550