summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorNeil Brown <neilb@cse.unsw.edu.au>2003-05-20 06:20:41 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-05-20 06:20:41 -0700
commit448d25b80b05679c2d70438530b9cff354eb3d7a (patch)
treed97334c2afb25cc71aa64bc3a3d742157fda3824 /include
parent9c88ef1f872a99f914b8fe607d01ecd2a965c34b (diff)
[PATCH] kNFSd: NFSv4 open share state patch
From: "William A.(Andy) Adamson" <andros@citi.umich.edu> this open share state patch creates all the structures and hash tables needed to create and destroy share state on OPEN. a struct nfs4_stateowner is introduced. this is currently only used for share state, but will also be used as an anchor for byte-range lock state. e.g. it will be either an (open)stateowner or a (lock)stateower. a struct nfs4_stateid is introduced with holds stateid info for openfiles per (open)stateowner. this struct will also hold byte-range lock info for (lock)stateowners. ownerstr_hashtbl[] holds nfs4_stateowners hashed by the nfs4_open owner and clientid, and is used to lookup nfs4_stateowners on OPEN. a struct nfs4_file is introduced which holds info on open files with state. file_hashtbl[] holds nfs4_files, and is used to find a file in order to search for conflicting share locks on OPEN. delegation info will hang off the nf4_file struct. i moved nfsd4_process_open1() into nfs4state.c, and added nfs4_process_open2() there as well i've left lease management, state reclaim, and the special replay management on sequenceid mutating operations like OPEN for subsequent patches.
Diffstat (limited to 'include')
-rw-r--r--include/linux/nfs.h9
-rw-r--r--include/linux/nfsd/nfsd.h6
-rw-r--r--include/linux/nfsd/state.h66
-rw-r--r--include/linux/nfsd/xdr4.h4
4 files changed, 80 insertions, 5 deletions
diff --git a/include/linux/nfs.h b/include/linux/nfs.h
index d99650a19b55..a68c459779e8 100644
--- a/include/linux/nfs.h
+++ b/include/linux/nfs.h
@@ -85,9 +85,9 @@
NFSERR_NOFILEHANDLE = 10020, /* v4 */
NFSERR_MINOR_VERS_MISMATCH = 10021, /* v4 */
NFSERR_STALE_CLIENTID = 10022, /* v4 */
- NFSERR_STALE_STATEID = 10023, /* v4 */
- NFSERR_OLD_STATEID = 10024, /* v4 */
- NFSERR_BAD_STATEID = 10025, /* v4 */
+ NFSERR_STALE_STATEID = 10023, /* v4 */
+ NFSERR_OLD_STATEID = 10024, /* v4 */
+ NFSERR_BAD_STATEID = 10025, /* v4 */
NFSERR_BAD_SEQID = 10026, /* v4 */
NFSERR_NOT_SAME = 10027, /* v4 */
NFSERR_LOCK_RANGE = 10028, /* v4 */
@@ -99,7 +99,8 @@
NFSERR_RECLAIM_BAD = 10034, /* v4 */
NFSERR_RECLAIM_CONFLICT = 10035,/* v4 */
NFSERR_BAD_XDR = 10036, /* v4 */
- NFSERR_LOCKS_HELD = 10037 /* v4 */
+ NFSERR_LOCKS_HELD = 10037, /* v4 */
+ NFSERR_REPLAY_ME = 10038 /* v4 */
};
/* NFSv2 file types - beware, these are not the same in NFSv3 */
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 379b77114c5b..c7726a375b38 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -170,6 +170,7 @@ void nfsd_lockd_shutdown(void);
#define nfserr_serverfault __constant_htonl(NFSERR_SERVERFAULT)
#define nfserr_badtype __constant_htonl(NFSERR_BADTYPE)
#define nfserr_jukebox __constant_htonl(NFSERR_JUKEBOX)
+#define nfserr_expired __constant_htonl(NFSERR_EXPIRED)
#define nfserr_bad_cookie __constant_htonl(NFSERR_BAD_COOKIE)
#define nfserr_same __constant_htonl(NFSERR_SAME)
#define nfserr_clid_inuse __constant_htonl(NFSERR_CLID_INUSE)
@@ -177,6 +178,11 @@ void nfsd_lockd_shutdown(void);
#define nfserr_resource __constant_htonl(NFSERR_RESOURCE)
#define nfserr_nofilehandle __constant_htonl(NFSERR_NOFILEHANDLE)
#define nfserr_minor_vers_mismatch __constant_htonl(NFSERR_MINOR_VERS_MISMATCH)
+#define nfserr_share_denied __constant_htonl(NFSERR_SHARE_DENIED)
+#define nfserr_stale_stateid __constant_htonl(NFSERR_STALE_STATEID)
+#define nfserr_old_stateid __constant_htonl(NFSERR_OLD_STATEID)
+#define nfserr_bad_stateid __constant_htonl(NFSERR_BAD_STATEID)
+#define nfserr_bad_seqid __constant_htonl(NFSERR_BAD_SEQID)
#define nfserr_symlink __constant_htonl(NFSERR_SYMLINK)
#define nfserr_not_same __constant_htonl(NFSERR_NOT_SAME)
#define nfserr_readdir_nospc __constant_htonl(NFSERR_READDIR_NOSPC)
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 51ee4f74b68a..11327bf38604 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -65,10 +65,14 @@ typedef struct {
*
* o Each nfs4_clients is also hashed by name
* (the opaque quantity initially sent by the client to identify itself).
+ *
+ * o cl_perclient list is used to ensure no dangling stateowner references
+ * when we expire the nfs4_client
*/
struct nfs4_client {
struct list_head cl_idhash; /* hash by cl_clientid.id */
struct list_head cl_strhash; /* hash by cl_name */
+ struct list_head cl_perclient; /* list: stateowners */
struct xdr_netobj cl_name; /* id generated by client */
nfs4_verifier cl_verifier; /* generated by client */
u32 cl_addr; /* client ipaddress */
@@ -76,4 +80,66 @@ struct nfs4_client {
clientid_t cl_clientid; /* generated by server */
nfs4_verifier cl_confirm; /* generated by server */
};
+
+static inline void
+update_stateid(stateid_t *stateid)
+{
+stateid->si_generation++;
+}
+
+
+/*
+* nfs4_stateowner can either be an open_owner, or (eventually) a lock_owner
+*
+* o so_peropenstate list is used to ensure no dangling nfs4_stateid
+* reverences when we release a stateowner.
+*/
+struct nfs4_stateowner {
+ struct list_head so_strhash; /* hash by op_name */
+ struct list_head so_perclient; /* nfs4_client->cl_perclient */
+ struct list_head so_peropenstate; /* list: nfs4_stateid */
+ u32 so_id;
+ struct nfs4_client * so_client;
+ u32 so_seqid;
+ struct xdr_netobj so_owner; /* open owner name */
+ int so_confirmed; /* successful OPEN_CONFIRM? */
+};
+
+typedef struct {
+ u32 dev; /* super_block->s_dev */
+ unsigned long ino;
+ u32 generation;
+} nfs4_ino_desc_t;
+
+/*
+* nfs4_file: a file opened by some number of (open) nfs4_stateowners.
+* o fi_perfile list is used to search for conflicting
+* share_acces, share_deny on the file.
+*/
+struct nfs4_file {
+ struct list_head fi_hash; /* hash by nfs4_ino_desc_t fields */
+ struct list_head fi_perfile; /* list: nfs4_stateid */
+ nfs4_ino_desc_t fi_ino;
+ u32 fi_id; /* used with stateowner->so_id
+ * for openstateid_hashtbl hash */
+};
+
+/*
+* nfs4_stateid can either be an open stateid or (eventually) a lock stateid
+*
+* (open)nfs4_stateid: one per (open)nfs4_stateowner, nfs4_file
+*/
+
+struct nfs4_stateid {
+ struct list_head st_perfile; /* file_hashtbl[]*/
+ struct list_head st_peropenstate; /* nfs4_stateowner->so_peropenstate */
+ struct nfs4_stateowner * st_stateowner;
+ struct nfs4_file * st_file;
+ stateid_t st_stateid;
+ struct file st_vfs_file;
+ int st_vfs_set;
+ unsigned int st_share_access;
+ unsigned int st_share_deny;
+};
+
#endif /* NFSD4_STATE_H */
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 00040f56e697..2d670ad4893d 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -141,6 +141,7 @@ struct nfsd4_open {
struct nfsd4_change_info op_cinfo; /* response */
u32 op_rflags; /* response */
int op_truncate; /* used during processing */
+ struct nfs4_stateowner *op_stateowner; /* used during processing */
};
#define op_iattr u.iattr
@@ -322,7 +323,8 @@ int nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
struct dentry *dentry, u32 *buffer, int *countp, u32 *bmval);
extern int nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid);
extern int nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm);
-
+extern int nfsd4_process_open1(struct nfsd4_open *open);
+extern int nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open);
#endif
/*