| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  *  linux/include/nfsd/state.h | 
 | 3 |  * | 
 | 4 |  *  Copyright (c) 2001 The Regents of the University of Michigan. | 
 | 5 |  *  All rights reserved. | 
 | 6 |  * | 
 | 7 |  *  Kendrick Smith <kmsmith@umich.edu> | 
 | 8 |  *  Andy Adamson <andros@umich.edu> | 
 | 9 |  *   | 
 | 10 |  *  Redistribution and use in source and binary forms, with or without | 
 | 11 |  *  modification, are permitted provided that the following conditions | 
 | 12 |  *  are met: | 
 | 13 |  *   | 
 | 14 |  *  1. Redistributions of source code must retain the above copyright | 
 | 15 |  *     notice, this list of conditions and the following disclaimer. | 
 | 16 |  *  2. Redistributions in binary form must reproduce the above copyright | 
 | 17 |  *     notice, this list of conditions and the following disclaimer in the | 
 | 18 |  *     documentation and/or other materials provided with the distribution. | 
 | 19 |  *  3. Neither the name of the University nor the names of its | 
 | 20 |  *     contributors may be used to endorse or promote products derived | 
 | 21 |  *     from this software without specific prior written permission. | 
 | 22 |  * | 
 | 23 |  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | 
 | 24 |  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 
 | 25 |  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
 | 26 |  *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 
 | 27 |  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 
 | 28 |  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 
 | 29 |  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | 
 | 30 |  *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 
 | 31 |  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
 | 32 |  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
 | 33 |  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
 | 34 |  * | 
 | 35 |  */ | 
 | 36 |  | 
 | 37 | #ifndef _NFSD4_STATE_H | 
 | 38 | #define _NFSD4_STATE_H | 
 | 39 |  | 
 | 40 | #include <linux/list.h> | 
 | 41 | #include <linux/kref.h> | 
 | 42 | #include <linux/sunrpc/clnt.h> | 
 | 43 |  | 
 | 44 | #define NFS4_OPAQUE_LIMIT 1024 | 
 | 45 | typedef struct { | 
 | 46 | 	u32             cl_boot; | 
 | 47 | 	u32             cl_id; | 
 | 48 | } clientid_t; | 
 | 49 |  | 
 | 50 | typedef struct { | 
 | 51 | 	u32             so_boot; | 
 | 52 | 	u32             so_stateownerid; | 
 | 53 | 	u32             so_fileid; | 
 | 54 | } stateid_opaque_t; | 
 | 55 |  | 
 | 56 | typedef struct { | 
 | 57 | 	u32                     si_generation; | 
 | 58 | 	stateid_opaque_t        si_opaque; | 
 | 59 | } stateid_t; | 
 | 60 | #define si_boot           si_opaque.so_boot | 
 | 61 | #define si_stateownerid   si_opaque.so_stateownerid | 
 | 62 | #define si_fileid         si_opaque.so_fileid | 
 | 63 |  | 
 | 64 | extern stateid_t zerostateid; | 
 | 65 | extern stateid_t onestateid; | 
 | 66 |  | 
 | 67 | #define ZERO_STATEID(stateid)       (!memcmp((stateid), &zerostateid, sizeof(stateid_t))) | 
 | 68 | #define ONE_STATEID(stateid)        (!memcmp((stateid), &onestateid, sizeof(stateid_t))) | 
 | 69 |  | 
 | 70 | struct nfs4_cb_recall { | 
 | 71 | 	u32			cbr_ident; | 
 | 72 | 	int			cbr_trunc; | 
 | 73 | 	stateid_t		cbr_stateid; | 
 | 74 | 	u32			cbr_fhlen; | 
 | 75 | 	u32			cbr_fhval[NFS4_FHSIZE]; | 
 | 76 | 	struct nfs4_delegation	*cbr_dp; | 
 | 77 | }; | 
 | 78 |  | 
 | 79 | struct nfs4_delegation { | 
 | 80 | 	struct list_head	dl_del_perfile; /* nfs4_file->fi_del_perfile */ | 
 | 81 | 	struct list_head	dl_del_perclnt; /* nfs4_client->cl_del_perclnt*/ | 
 | 82 | 	struct list_head	dl_recall_lru;  /* delegation recalled */ | 
 | 83 | 	atomic_t		dl_count;       /* ref count */ | 
 | 84 | 	struct nfs4_client	*dl_client; | 
 | 85 | 	struct nfs4_file	*dl_file; | 
 | 86 | 	struct file_lock	*dl_flock; | 
 | 87 | 	struct file		*dl_vfs_file; | 
 | 88 | 	u32			dl_type; | 
 | 89 | 	time_t			dl_time; | 
 | 90 | 	struct nfs4_cb_recall	dl_recall; | 
 | 91 | }; | 
 | 92 |  | 
 | 93 | #define dl_stateid      dl_recall.cbr_stateid | 
 | 94 | #define dl_fhlen        dl_recall.cbr_fhlen | 
 | 95 | #define dl_fhval        dl_recall.cbr_fhval | 
 | 96 |  | 
 | 97 | /* client delegation callback info */ | 
 | 98 | struct nfs4_callback { | 
 | 99 | 	/* SETCLIENTID info */ | 
 | 100 | 	u32			cb_parsed;  /* addr parsed */ | 
 | 101 | 	u32                     cb_addr; | 
 | 102 | 	unsigned short          cb_port; | 
 | 103 | 	u32                     cb_prog; | 
 | 104 | 	u32                     cb_ident; | 
 | 105 | 	/* RPC client info */ | 
 | 106 | 	atomic_t		cb_set;     /* successful CB_NULL call */ | 
 | 107 | 	struct rpc_program      cb_program; | 
 | 108 | 	struct rpc_stat         cb_stat; | 
 | 109 | 	struct rpc_clnt *       cb_client; | 
 | 110 | }; | 
 | 111 |  | 
 | 112 | /* | 
 | 113 |  * struct nfs4_client - one per client.  Clientids live here. | 
 | 114 |  * 	o Each nfs4_client is hashed by clientid. | 
 | 115 |  * | 
 | 116 |  * 	o Each nfs4_clients is also hashed by name  | 
 | 117 |  * 	  (the opaque quantity initially sent by the client to identify itself). | 
 | 118 |  * 	   | 
 | 119 |  *	o cl_perclient list is used to ensure no dangling stateowner references | 
 | 120 |  *	  when we expire the nfs4_client | 
 | 121 |  */ | 
 | 122 | struct nfs4_client { | 
 | 123 | 	struct list_head	cl_idhash; 	/* hash by cl_clientid.id */ | 
 | 124 | 	struct list_head	cl_strhash; 	/* hash by cl_name */ | 
 | 125 | 	struct list_head	cl_perclient; 	/* list: stateowners */ | 
 | 126 | 	struct list_head	cl_del_perclnt; /* list: delegations */ | 
 | 127 | 	struct list_head        cl_lru;         /* tail queue */ | 
 | 128 | 	struct xdr_netobj	cl_name; 	/* id generated by client */ | 
 | 129 | 	nfs4_verifier		cl_verifier; 	/* generated by client */ | 
 | 130 | 	time_t                  cl_time;        /* time of last lease renewal */ | 
 | 131 | 	u32			cl_addr; 	/* client ipaddress */ | 
 | 132 | 	struct svc_cred		cl_cred; 	/* setclientid principal */ | 
 | 133 | 	clientid_t		cl_clientid;	/* generated by server */ | 
 | 134 | 	nfs4_verifier		cl_confirm;	/* generated by server */ | 
 | 135 | 	struct nfs4_callback	cl_callback;    /* callback info */ | 
 | 136 | 	atomic_t		cl_count;	/* ref count */ | 
 | 137 | }; | 
 | 138 |  | 
 | 139 | /* struct nfs4_client_reset | 
 | 140 |  * one per old client. Populates reset_str_hashtbl. Filled from conf_id_hashtbl | 
 | 141 |  * upon lease reset, or from upcall to state_daemon (to read in state | 
 | 142 |  * from non-volitile storage) upon reboot. | 
 | 143 |  */ | 
 | 144 | struct nfs4_client_reclaim { | 
 | 145 | 	struct list_head	cr_strhash;	/* hash by cr_name */ | 
 | 146 | 	struct xdr_netobj 	cr_name; 	/* id generated by client */ | 
 | 147 | }; | 
 | 148 |  | 
 | 149 | static inline void | 
 | 150 | update_stateid(stateid_t *stateid) | 
 | 151 | { | 
 | 152 | 	stateid->si_generation++; | 
 | 153 | } | 
 | 154 |  | 
 | 155 | /* A reasonable value for REPLAY_ISIZE was estimated as follows:   | 
 | 156 |  * The OPEN response, typically the largest, requires  | 
 | 157 |  *   4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) +  8(verifier) +  | 
 | 158 |  *   4(deleg. type) + 8(deleg. stateid) + 4(deleg. recall flag) +  | 
 | 159 |  *   20(deleg. space limit) + ~32(deleg. ace) = 112 bytes  | 
 | 160 |  */ | 
 | 161 |  | 
 | 162 | #define NFSD4_REPLAY_ISIZE       112  | 
 | 163 |  | 
 | 164 | /* | 
 | 165 |  * Replay buffer, where the result of the last seqid-mutating operation  | 
 | 166 |  * is cached.  | 
 | 167 |  */ | 
 | 168 | struct nfs4_replay { | 
 | 169 | 	u32			rp_status; | 
 | 170 | 	unsigned int		rp_buflen; | 
 | 171 | 	char			*rp_buf; | 
 | 172 | 	unsigned		intrp_allocated; | 
 | 173 | 	int			rp_openfh_len; | 
 | 174 | 	char			rp_openfh[NFS4_FHSIZE]; | 
 | 175 | 	char			rp_ibuf[NFSD4_REPLAY_ISIZE]; | 
 | 176 | }; | 
 | 177 |  | 
 | 178 | /* | 
 | 179 | * nfs4_stateowner can either be an open_owner, or a lock_owner | 
 | 180 | * | 
 | 181 | *    so_idhash:  stateid_hashtbl[] for open owner, lockstateid_hashtbl[] | 
 | 182 | *         for lock_owner | 
 | 183 | *    so_strhash: ownerstr_hashtbl[] for open_owner, lock_ownerstr_hashtbl[] | 
 | 184 | *         for lock_owner | 
 | 185 | *    so_perclient: nfs4_client->cl_perclient entry - used when nfs4_client | 
 | 186 | *         struct is reaped. | 
 | 187 | *    so_perfilestate: heads the list of nfs4_stateid (either open or lock)  | 
 | 188 | *         and is used to ensure no dangling nfs4_stateid references when we  | 
 | 189 | *         release a stateowner. | 
 | 190 | *    so_perlockowner: (open) nfs4_stateid->st_perlockowner entry - used when | 
 | 191 | *         close is called to reap associated byte-range locks | 
 | 192 | *    so_close_lru: (open) stateowner is placed on this list instead of being | 
 | 193 | *         reaped (when so_perfilestate is empty) to hold the last close replay. | 
 | 194 | *         reaped by laundramat thread after lease period. | 
 | 195 | */ | 
 | 196 | struct nfs4_stateowner { | 
 | 197 | 	struct kref		so_ref; | 
 | 198 | 	struct list_head        so_idhash;   /* hash by so_id */ | 
 | 199 | 	struct list_head        so_strhash;   /* hash by op_name */ | 
 | 200 | 	struct list_head        so_perclient; /* nfs4_client->cl_perclient */ | 
 | 201 | 	struct list_head        so_perfilestate; /* list: nfs4_stateid */ | 
 | 202 | 	struct list_head        so_perlockowner; /* nfs4_stateid->st_perlockowner */ | 
 | 203 | 	struct list_head	so_close_lru; /* tail queue */ | 
 | 204 | 	time_t			so_time; /* time of placement on so_close_lru */ | 
 | 205 | 	int			so_is_open_owner; /* 1=openowner,0=lockowner */ | 
 | 206 | 	u32                     so_id; | 
 | 207 | 	struct nfs4_client *    so_client; | 
 | 208 | 	u32                     so_seqid;     | 
 | 209 | 	struct xdr_netobj       so_owner;     /* open owner name */ | 
 | 210 | 	int                     so_confirmed; /* successful OPEN_CONFIRM? */ | 
 | 211 | 	struct nfs4_replay	so_replay; | 
 | 212 | }; | 
 | 213 |  | 
 | 214 | /* | 
 | 215 | *  nfs4_file: a file opened by some number of (open) nfs4_stateowners. | 
 | 216 | *    o fi_perfile list is used to search for conflicting  | 
 | 217 | *      share_acces, share_deny on the file. | 
 | 218 | */ | 
 | 219 | struct nfs4_file { | 
 | 220 | 	struct list_head        fi_hash;    /* hash by "struct inode *" */ | 
 | 221 | 	struct list_head        fi_perfile; /* list: nfs4_stateid */ | 
 | 222 | 	struct list_head	fi_del_perfile; /* list: nfs4_delegation */ | 
 | 223 | 	struct inode		*fi_inode; | 
 | 224 | 	u32                     fi_id;      /* used with stateowner->so_id  | 
 | 225 | 					     * for stateid_hashtbl hash */ | 
 | 226 | }; | 
 | 227 |  | 
 | 228 | /* | 
 | 229 | * nfs4_stateid can either be an open stateid or (eventually) a lock stateid | 
 | 230 | * | 
 | 231 | * (open)nfs4_stateid: one per (open)nfs4_stateowner, nfs4_file | 
 | 232 | * | 
 | 233 | * 	st_hash: stateid_hashtbl[] entry or lockstateid_hashtbl entry | 
 | 234 | * 	st_perfile: file_hashtbl[] entry. | 
 | 235 | * 	st_perfile_state: nfs4_stateowner->so_perfilestate | 
 | 236 | *       st_perlockowner: (open stateid) list of lock nfs4_stateowners | 
 | 237 | * 	st_access_bmap: used only for open stateid | 
 | 238 | * 	st_deny_bmap: used only for open stateid | 
 | 239 | */ | 
 | 240 |  | 
 | 241 | struct nfs4_stateid { | 
 | 242 | 	struct list_head              st_hash;  | 
 | 243 | 	struct list_head              st_perfile; | 
 | 244 | 	struct list_head              st_perfilestate;  | 
 | 245 | 	struct list_head              st_perlockowner; | 
 | 246 | 	struct nfs4_stateowner      * st_stateowner; | 
 | 247 | 	struct nfs4_file            * st_file; | 
 | 248 | 	stateid_t                     st_stateid; | 
 | 249 | 	struct file                 * st_vfs_file; | 
 | 250 | 	unsigned long                 st_access_bmap; | 
 | 251 | 	unsigned long                 st_deny_bmap; | 
 | 252 | }; | 
 | 253 |  | 
 | 254 | /* flags for preprocess_seqid_op() */ | 
 | 255 | #define CHECK_FH                0x00000001 | 
 | 256 | #define CONFIRM                 0x00000002 | 
 | 257 | #define OPEN_STATE              0x00000004 | 
 | 258 | #define LOCK_STATE              0x00000008 | 
 | 259 | #define RD_STATE	        0x00000010 | 
 | 260 | #define WR_STATE	        0x00000020 | 
 | 261 | #define CLOSE_STATE             0x00000040 | 
 | 262 | #define DELEG_RET               0x00000080 | 
 | 263 |  | 
 | 264 | #define seqid_mutating_err(err)                       \ | 
 | 265 | 	(((err) != nfserr_stale_clientid) &&    \ | 
 | 266 | 	((err) != nfserr_bad_seqid) &&          \ | 
 | 267 | 	((err) != nfserr_stale_stateid) &&      \ | 
 | 268 | 	((err) != nfserr_bad_stateid)) | 
 | 269 |  | 
 | 270 | extern time_t nfs4_laundromat(void); | 
 | 271 | extern int nfsd4_renew(clientid_t *clid); | 
 | 272 | extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh,  | 
 | 273 | 		stateid_t *stateid, int flags, struct file **filp); | 
 | 274 | extern int nfs4_share_conflict(struct svc_fh *current_fh,  | 
 | 275 | 		unsigned int deny_type); | 
 | 276 | extern void nfs4_lock_state(void); | 
 | 277 | extern void nfs4_unlock_state(void); | 
 | 278 | extern int nfs4_in_grace(void); | 
 | 279 | extern int nfs4_check_open_reclaim(clientid_t *clid); | 
 | 280 | extern void put_nfs4_client(struct nfs4_client *clp); | 
 | 281 | extern void nfs4_free_stateowner(struct kref *kref); | 
 | 282 | extern void nfsd4_probe_callback(struct nfs4_client *clp); | 
 | 283 | extern void nfsd4_cb_recall(struct nfs4_delegation *dp); | 
 | 284 | extern void nfs4_put_delegation(struct nfs4_delegation *dp); | 
 | 285 |  | 
 | 286 | static inline void | 
 | 287 | nfs4_put_stateowner(struct nfs4_stateowner *so) | 
 | 288 | { | 
 | 289 | 	kref_put(&so->so_ref, nfs4_free_stateowner); | 
 | 290 | } | 
 | 291 |  | 
 | 292 | static inline void | 
 | 293 | nfs4_get_stateowner(struct nfs4_stateowner *so) | 
 | 294 | { | 
 | 295 | 	kref_get(&so->so_ref); | 
 | 296 | } | 
 | 297 |  | 
 | 298 | #endif   /* NFSD4_STATE_H */ |