Commit 448d25b8 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[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.
parent 9c88ef1f
......@@ -108,45 +108,25 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
return status;
}
static int
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
struct iattr iattr;
int status;
if (open->op_truncate) {
iattr.ia_valid = ATTR_SIZE;
iattr.ia_size = 0;
status = nfsd_setattr(rqstp, current_fh, &iattr, 0, (time_t)0);
if (status)
return status;
}
memset(&open->op_stateid, 0xff, sizeof(stateid_t));
open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
return 0;
}
static inline int
nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
int status;
dprintk("NFSD: nfsd4_open filename %.*s\n",open->op_fname.len, open->op_fname.data);
/* This check required by spec. */
if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
return nfserr_inval;
/*
* For now, we have no state, so we may as well implement an
* even stronger check...
*/
if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
return nfserr_notsupp;
/* check seqid for replay. set nfs4_owner */
status = nfsd4_process_open1(open);
if (status)
return status;
/*
* This block of code will (1) set CURRENT_FH to the file being opened,
* creating it if necessary, (2) set open->op_cinfo, (3) set open->op_truncate
* if the file is to be truncated after opening, (4) do permission checking.
* creating it if necessary, (2) set open->op_cinfo,
* (3) set open->op_truncate if the file is to be truncated
* after opening, (4) do permission checking.
*/
status = do_open_lookup(rqstp, current_fh, open);
if (status)
......@@ -160,7 +140,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
status = nfsd4_process_open2(rqstp, current_fh, open);
if (status)
return status;
/*
* To finish the open response, we just need to set the rflags.
*/
......
This diff is collapsed.
......@@ -472,7 +472,6 @@ static void __exit exit_nfsd(void)
remove_proc_entry("fs/nfs", NULL);
nfsd_stat_shutdown();
nfsd_lockd_shutdown();
nfs4_state_shutdown();
unregister_filesystem(&nfsd_fs_type);
}
......
......@@ -132,6 +132,7 @@ nfsd_svc(unsigned short port, int nrservs)
if (none_left) {
nfsd_serv = NULL;
nfsd_racache_shutdown();
nfs4_state_shutdown();
}
out:
unlock_kernel();
......@@ -247,6 +248,7 @@ nfsd(struct svc_rqst *rqstp)
}
nfsd_serv = NULL;
nfsd_racache_shutdown(); /* release read-ahead cache */
nfs4_state_shutdown();
}
list_del(&me.list);
nfsdstats.th_cnt --;
......
......@@ -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 */
......
......@@ -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)
......
......@@ -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 */
......@@ -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
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment