aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/state.h
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/state.h')
-rw-r--r--fs/nfsd/state.h220
1 files changed, 146 insertions, 74 deletions
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 374c66283ac5..4a89e00d7461 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -72,7 +72,13 @@ struct nfsd4_callback {
72 bool cb_done; 72 bool cb_done;
73}; 73};
74 74
75/*
76 * A core object that represents a "common" stateid. These are generally
77 * embedded within the different (more specific) stateid objects and contain
78 * fields that are of general use to any stateid.
79 */
75struct nfs4_stid { 80struct nfs4_stid {
81 atomic_t sc_count;
76#define NFS4_OPEN_STID 1 82#define NFS4_OPEN_STID 1
77#define NFS4_LOCK_STID 2 83#define NFS4_LOCK_STID 2
78#define NFS4_DELEG_STID 4 84#define NFS4_DELEG_STID 4
@@ -80,22 +86,43 @@ struct nfs4_stid {
80#define NFS4_CLOSED_STID 8 86#define NFS4_CLOSED_STID 8
81/* For a deleg stateid kept around only to process free_stateid's: */ 87/* For a deleg stateid kept around only to process free_stateid's: */
82#define NFS4_REVOKED_DELEG_STID 16 88#define NFS4_REVOKED_DELEG_STID 16
89#define NFS4_CLOSED_DELEG_STID 32
83 unsigned char sc_type; 90 unsigned char sc_type;
84 stateid_t sc_stateid; 91 stateid_t sc_stateid;
85 struct nfs4_client *sc_client; 92 struct nfs4_client *sc_client;
93 struct nfs4_file *sc_file;
94 void (*sc_free)(struct nfs4_stid *);
86}; 95};
87 96
97/*
98 * Represents a delegation stateid. The nfs4_client holds references to these
99 * and they are put when it is being destroyed or when the delegation is
100 * returned by the client:
101 *
102 * o 1 reference as long as a delegation is still in force (taken when it's
103 * alloc'd, put when it's returned or revoked)
104 *
105 * o 1 reference as long as a recall rpc is in progress (taken when the lease
106 * is broken, put when the rpc exits)
107 *
108 * o 1 more ephemeral reference for each nfsd thread currently doing something
109 * with that delegation without holding the cl_lock
110 *
111 * If the server attempts to recall a delegation and the client doesn't do so
112 * before a timeout, the server may also revoke the delegation. In that case,
113 * the object will either be destroyed (v4.0) or moved to a per-client list of
114 * revoked delegations (v4.1+).
115 *
116 * This object is a superset of the nfs4_stid.
117 */
88struct nfs4_delegation { 118struct nfs4_delegation {
89 struct nfs4_stid dl_stid; /* must be first field */ 119 struct nfs4_stid dl_stid; /* must be first field */
90 struct list_head dl_perfile; 120 struct list_head dl_perfile;
91 struct list_head dl_perclnt; 121 struct list_head dl_perclnt;
92 struct list_head dl_recall_lru; /* delegation recalled */ 122 struct list_head dl_recall_lru; /* delegation recalled */
93 atomic_t dl_count; /* ref count */
94 struct nfs4_file *dl_file;
95 u32 dl_type; 123 u32 dl_type;
96 time_t dl_time; 124 time_t dl_time;
97/* For recall: */ 125/* For recall: */
98 struct knfsd_fh dl_fh;
99 int dl_retries; 126 int dl_retries;
100 struct nfsd4_callback dl_recall; 127 struct nfsd4_callback dl_recall;
101}; 128};
@@ -194,6 +221,11 @@ struct nfsd4_conn {
194 unsigned char cn_flags; 221 unsigned char cn_flags;
195}; 222};
196 223
224/*
225 * Representation of a v4.1+ session. These are refcounted in a similar fashion
226 * to the nfs4_client. References are only taken when the server is actively
227 * working on the object (primarily during the processing of compounds).
228 */
197struct nfsd4_session { 229struct nfsd4_session {
198 atomic_t se_ref; 230 atomic_t se_ref;
199 struct list_head se_hash; /* hash by sessionid */ 231 struct list_head se_hash; /* hash by sessionid */
@@ -212,8 +244,6 @@ struct nfsd4_session {
212 struct nfsd4_slot *se_slots[]; /* forward channel slots */ 244 struct nfsd4_slot *se_slots[]; /* forward channel slots */
213}; 245};
214 246
215extern void nfsd4_put_session(struct nfsd4_session *ses);
216
217/* formatted contents of nfs4_sessionid */ 247/* formatted contents of nfs4_sessionid */
218struct nfsd4_sessionid { 248struct nfsd4_sessionid {
219 clientid_t clientid; 249 clientid_t clientid;
@@ -225,17 +255,35 @@ struct nfsd4_sessionid {
225 255
226/* 256/*
227 * struct nfs4_client - one per client. Clientids live here. 257 * struct nfs4_client - one per client. Clientids live here.
228 * o Each nfs4_client is hashed by clientid.
229 * 258 *
230 * o Each nfs4_clients is also hashed by name 259 * The initial object created by an NFS client using SETCLIENTID (for NFSv4.0)
231 * (the opaque quantity initially sent by the client to identify itself). 260 * or EXCHANGE_ID (for NFSv4.1+). These objects are refcounted and timestamped.
261 * Each nfsd_net_ns object contains a set of these and they are tracked via
262 * short and long form clientid. They are hashed and searched for under the
263 * per-nfsd_net client_lock spinlock.
264 *
265 * References to it are only held during the processing of compounds, and in
266 * certain other operations. In their "resting state" they have a refcount of
267 * 0. If they are not renewed within a lease period, they become eligible for
268 * destruction by the laundromat.
269 *
270 * These objects can also be destroyed prematurely by the fault injection code,
271 * or if the client sends certain forms of SETCLIENTID or EXCHANGE_ID updates.
272 * Care is taken *not* to do this however when the objects have an elevated
273 * refcount.
274 *
275 * o Each nfs4_client is hashed by clientid
276 *
277 * o Each nfs4_clients is also hashed by name (the opaque quantity initially
278 * sent by the client to identify itself).
232 * 279 *
233 * o cl_perclient list is used to ensure no dangling stateowner references 280 * o cl_perclient list is used to ensure no dangling stateowner references
234 * when we expire the nfs4_client 281 * when we expire the nfs4_client
235 */ 282 */
236struct nfs4_client { 283struct nfs4_client {
237 struct list_head cl_idhash; /* hash by cl_clientid.id */ 284 struct list_head cl_idhash; /* hash by cl_clientid.id */
238 struct rb_node cl_namenode; /* link into by-name trees */ 285 struct rb_node cl_namenode; /* link into by-name trees */
286 struct list_head *cl_ownerstr_hashtbl;
239 struct list_head cl_openowners; 287 struct list_head cl_openowners;
240 struct idr cl_stateids; /* stateid lookup */ 288 struct idr cl_stateids; /* stateid lookup */
241 struct list_head cl_delegations; 289 struct list_head cl_delegations;
@@ -329,21 +377,43 @@ struct nfs4_replay {
329 unsigned int rp_buflen; 377 unsigned int rp_buflen;
330 char *rp_buf; 378 char *rp_buf;
331 struct knfsd_fh rp_openfh; 379 struct knfsd_fh rp_openfh;
380 struct mutex rp_mutex;
332 char rp_ibuf[NFSD4_REPLAY_ISIZE]; 381 char rp_ibuf[NFSD4_REPLAY_ISIZE];
333}; 382};
334 383
384struct nfs4_stateowner;
385
386struct nfs4_stateowner_operations {
387 void (*so_unhash)(struct nfs4_stateowner *);
388 void (*so_free)(struct nfs4_stateowner *);
389};
390
391/*
392 * A core object that represents either an open or lock owner. The object and
393 * lock owner objects have one of these embedded within them. Refcounts and
394 * other fields common to both owner types are contained within these
395 * structures.
396 */
335struct nfs4_stateowner { 397struct nfs4_stateowner {
336 struct list_head so_strhash; /* hash by op_name */ 398 struct list_head so_strhash;
337 struct list_head so_stateids; 399 struct list_head so_stateids;
338 struct nfs4_client * so_client; 400 struct nfs4_client *so_client;
339 /* after increment in ENCODE_SEQID_OP_TAIL, represents the next 401 const struct nfs4_stateowner_operations *so_ops;
402 /* after increment in nfsd4_bump_seqid, represents the next
340 * sequence id expected from the client: */ 403 * sequence id expected from the client: */
341 u32 so_seqid; 404 atomic_t so_count;
342 struct xdr_netobj so_owner; /* open owner name */ 405 u32 so_seqid;
343 struct nfs4_replay so_replay; 406 struct xdr_netobj so_owner; /* open owner name */
344 bool so_is_open_owner; 407 struct nfs4_replay so_replay;
408 bool so_is_open_owner;
345}; 409};
346 410
411/*
412 * When a file is opened, the client provides an open state owner opaque string
413 * that indicates the "owner" of that open. These objects are refcounted.
414 * References to it are held by each open state associated with it. This object
415 * is a superset of the nfs4_stateowner struct.
416 */
347struct nfs4_openowner { 417struct nfs4_openowner {
348 struct nfs4_stateowner oo_owner; /* must be first field */ 418 struct nfs4_stateowner oo_owner; /* must be first field */
349 struct list_head oo_perclient; 419 struct list_head oo_perclient;
@@ -358,15 +428,17 @@ struct nfs4_openowner {
358 struct nfs4_ol_stateid *oo_last_closed_stid; 428 struct nfs4_ol_stateid *oo_last_closed_stid;
359 time_t oo_time; /* time of placement on so_close_lru */ 429 time_t oo_time; /* time of placement on so_close_lru */
360#define NFS4_OO_CONFIRMED 1 430#define NFS4_OO_CONFIRMED 1
361#define NFS4_OO_NEW 4
362 unsigned char oo_flags; 431 unsigned char oo_flags;
363}; 432};
364 433
434/*
435 * Represents a generic "lockowner". Similar to an openowner. References to it
436 * are held by the lock stateids that are created on its behalf. This object is
437 * a superset of the nfs4_stateowner struct (or would be if it needed any extra
438 * fields).
439 */
365struct nfs4_lockowner { 440struct nfs4_lockowner {
366 struct nfs4_stateowner lo_owner; /* must be first element */ 441 struct nfs4_stateowner lo_owner; /* must be first element */
367 struct list_head lo_owner_ino_hash; /* hash by owner,file */
368 struct list_head lo_perstateid;
369 struct list_head lo_list; /* for temporary uses */
370}; 442};
371 443
372static inline struct nfs4_openowner * openowner(struct nfs4_stateowner *so) 444static inline struct nfs4_openowner * openowner(struct nfs4_stateowner *so)
@@ -379,9 +451,17 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so)
379 return container_of(so, struct nfs4_lockowner, lo_owner); 451 return container_of(so, struct nfs4_lockowner, lo_owner);
380} 452}
381 453
382/* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */ 454/*
455 * nfs4_file: a file opened by some number of (open) nfs4_stateowners.
456 *
457 * These objects are global. nfsd only keeps one instance of a nfs4_file per
458 * inode (though it may keep multiple file descriptors open per inode). These
459 * are tracked in the file_hashtbl which is protected by the state_lock
460 * spinlock.
461 */
383struct nfs4_file { 462struct nfs4_file {
384 atomic_t fi_ref; 463 atomic_t fi_ref;
464 spinlock_t fi_lock;
385 struct hlist_node fi_hash; /* hash by "struct inode *" */ 465 struct hlist_node fi_hash; /* hash by "struct inode *" */
386 struct list_head fi_stateids; 466 struct list_head fi_stateids;
387 struct list_head fi_delegations; 467 struct list_head fi_delegations;
@@ -395,49 +475,36 @@ struct nfs4_file {
395 * + 1 to both of the above if NFS4_SHARE_ACCESS_BOTH is set. 475 * + 1 to both of the above if NFS4_SHARE_ACCESS_BOTH is set.
396 */ 476 */
397 atomic_t fi_access[2]; 477 atomic_t fi_access[2];
478 u32 fi_share_deny;
398 struct file *fi_deleg_file; 479 struct file *fi_deleg_file;
399 struct file_lock *fi_lease; 480 struct file_lock *fi_lease;
400 atomic_t fi_delegees; 481 atomic_t fi_delegees;
401 struct inode *fi_inode; 482 struct knfsd_fh fi_fhandle;
402 bool fi_had_conflict; 483 bool fi_had_conflict;
403}; 484};
404 485
405/* XXX: for first cut may fall back on returning file that doesn't work 486/*
406 * at all? */ 487 * A generic struct representing either a open or lock stateid. The nfs4_client
407static inline struct file *find_writeable_file(struct nfs4_file *f) 488 * holds a reference to each of these objects, and they in turn hold a
408{ 489 * reference to their respective stateowners. The client's reference is
409 if (f->fi_fds[O_WRONLY]) 490 * released in response to a close or unlock (depending on whether it's an open
410 return f->fi_fds[O_WRONLY]; 491 * or lock stateid) or when the client is being destroyed.
411 return f->fi_fds[O_RDWR]; 492 *
412} 493 * In the case of v4.0 open stateids, these objects are preserved for a little
413 494 * while after close in order to handle CLOSE replays. Those are eventually
414static inline struct file *find_readable_file(struct nfs4_file *f) 495 * reclaimed via a LRU scheme by the laundromat.
415{ 496 *
416 if (f->fi_fds[O_RDONLY]) 497 * This object is a superset of the nfs4_stid. "ol" stands for "Open or Lock".
417 return f->fi_fds[O_RDONLY]; 498 * Better suggestions welcome.
418 return f->fi_fds[O_RDWR]; 499 */
419}
420
421static inline struct file *find_any_file(struct nfs4_file *f)
422{
423 if (f->fi_fds[O_RDWR])
424 return f->fi_fds[O_RDWR];
425 else if (f->fi_fds[O_WRONLY])
426 return f->fi_fds[O_WRONLY];
427 else
428 return f->fi_fds[O_RDONLY];
429}
430
431/* "ol" stands for "Open or Lock". Better suggestions welcome. */
432struct nfs4_ol_stateid { 500struct nfs4_ol_stateid {
433 struct nfs4_stid st_stid; /* must be first field */ 501 struct nfs4_stid st_stid; /* must be first field */
434 struct list_head st_perfile; 502 struct list_head st_perfile;
435 struct list_head st_perstateowner; 503 struct list_head st_perstateowner;
436 struct list_head st_lockowners; 504 struct list_head st_locks;
437 struct nfs4_stateowner * st_stateowner; 505 struct nfs4_stateowner * st_stateowner;
438 struct nfs4_file * st_file; 506 unsigned char st_access_bmap;
439 unsigned long st_access_bmap; 507 unsigned char st_deny_bmap;
440 unsigned long st_deny_bmap;
441 struct nfs4_ol_stateid * st_openstp; 508 struct nfs4_ol_stateid * st_openstp;
442}; 509};
443 510
@@ -456,15 +523,16 @@ struct nfsd_net;
456extern __be32 nfs4_preprocess_stateid_op(struct net *net, 523extern __be32 nfs4_preprocess_stateid_op(struct net *net,
457 struct nfsd4_compound_state *cstate, 524 struct nfsd4_compound_state *cstate,
458 stateid_t *stateid, int flags, struct file **filp); 525 stateid_t *stateid, int flags, struct file **filp);
459extern void nfs4_lock_state(void); 526void nfs4_put_stid(struct nfs4_stid *s);
460extern void nfs4_unlock_state(void);
461void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *); 527void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *);
462extern void nfs4_release_reclaim(struct nfsd_net *); 528extern void nfs4_release_reclaim(struct nfsd_net *);
463extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir, 529extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir,
464 struct nfsd_net *nn); 530 struct nfsd_net *nn);
465extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn); 531extern __be32 nfs4_check_open_reclaim(clientid_t *clid,
532 struct nfsd4_compound_state *cstate, struct nfsd_net *nn);
466extern int set_callback_cred(void); 533extern int set_callback_cred(void);
467extern void nfsd4_init_callback(struct nfsd4_callback *); 534void nfsd4_run_cb_null(struct work_struct *w);
535void nfsd4_run_cb_recall(struct work_struct *w);
468extern void nfsd4_probe_callback(struct nfs4_client *clp); 536extern void nfsd4_probe_callback(struct nfs4_client *clp);
469extern void nfsd4_probe_callback_sync(struct nfs4_client *clp); 537extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
470extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *); 538extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
@@ -472,11 +540,10 @@ extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
472extern int nfsd4_create_callback_queue(void); 540extern int nfsd4_create_callback_queue(void);
473extern void nfsd4_destroy_callback_queue(void); 541extern void nfsd4_destroy_callback_queue(void);
474extern void nfsd4_shutdown_callback(struct nfs4_client *); 542extern void nfsd4_shutdown_callback(struct nfs4_client *);
475extern void nfs4_put_delegation(struct nfs4_delegation *dp); 543extern void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp);
476extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name, 544extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
477 struct nfsd_net *nn); 545 struct nfsd_net *nn);
478extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn); 546extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
479extern void put_client_renew(struct nfs4_client *clp);
480 547
481/* nfs4recover operations */ 548/* nfs4recover operations */
482extern int nfsd4_client_tracking_init(struct net *net); 549extern int nfsd4_client_tracking_init(struct net *net);
@@ -490,19 +557,24 @@ extern void nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time);
490#ifdef CONFIG_NFSD_FAULT_INJECTION 557#ifdef CONFIG_NFSD_FAULT_INJECTION
491int nfsd_fault_inject_init(void); 558int nfsd_fault_inject_init(void);
492void nfsd_fault_inject_cleanup(void); 559void nfsd_fault_inject_cleanup(void);
493u64 nfsd_for_n_state(u64, u64 (*)(struct nfs4_client *, u64)); 560
494struct nfs4_client *nfsd_find_client(struct sockaddr_storage *, size_t); 561u64 nfsd_inject_print_clients(void);
495 562u64 nfsd_inject_forget_client(struct sockaddr_storage *, size_t);
496u64 nfsd_forget_client(struct nfs4_client *, u64); 563u64 nfsd_inject_forget_clients(u64);
497u64 nfsd_forget_client_locks(struct nfs4_client*, u64); 564
498u64 nfsd_forget_client_openowners(struct nfs4_client *, u64); 565u64 nfsd_inject_print_locks(void);
499u64 nfsd_forget_client_delegations(struct nfs4_client *, u64); 566u64 nfsd_inject_forget_client_locks(struct sockaddr_storage *, size_t);
500u64 nfsd_recall_client_delegations(struct nfs4_client *, u64); 567u64 nfsd_inject_forget_locks(u64);
501 568
502u64 nfsd_print_client(struct nfs4_client *, u64); 569u64 nfsd_inject_print_openowners(void);
503u64 nfsd_print_client_locks(struct nfs4_client *, u64); 570u64 nfsd_inject_forget_client_openowners(struct sockaddr_storage *, size_t);
504u64 nfsd_print_client_openowners(struct nfs4_client *, u64); 571u64 nfsd_inject_forget_openowners(u64);
505u64 nfsd_print_client_delegations(struct nfs4_client *, u64); 572
573u64 nfsd_inject_print_delegations(void);
574u64 nfsd_inject_forget_client_delegations(struct sockaddr_storage *, size_t);
575u64 nfsd_inject_forget_delegations(u64);
576u64 nfsd_inject_recall_client_delegations(struct sockaddr_storage *, size_t);
577u64 nfsd_inject_recall_delegations(u64);
506#else /* CONFIG_NFSD_FAULT_INJECTION */ 578#else /* CONFIG_NFSD_FAULT_INJECTION */
507static inline int nfsd_fault_inject_init(void) { return 0; } 579static inline int nfsd_fault_inject_init(void) { return 0; }
508static inline void nfsd_fault_inject_cleanup(void) {} 580static inline void nfsd_fault_inject_cleanup(void) {}