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