diff options
| author | Trond Myklebust <trond.myklebust@fys.uio.no> | 2003-04-08 04:26:25 +0200 |
|---|---|---|
| committer | Trond Myklebust <trond.myklebust@fys.uio.no> | 2003-04-08 04:26:25 +0200 |
| commit | 62175be2bd850d3c2db5065fb3ef4dff3272c068 (patch) | |
| tree | 6435333d79199ace68a2bd06a20b7be7c073e3b2 /include | |
| parent | ec059472a57fdabbac0d4e0e89a3b9547f88d62b (diff) | |
Implement stateful open() for NFSv4 as per RFC3010-bis.
The resulting state is saved in the NFS-specific part of the
struct inode.
Initially we just start with 3 possible states:
- open for read
- open for write
- open for read/write
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/nfs4.h | 2 | ||||
| -rw-r--r-- | include/linux/nfs_fs.h | 72 | ||||
| -rw-r--r-- | include/linux/nfs_xdr.h | 45 |
3 files changed, 110 insertions, 9 deletions
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 7c0d596db02f..02c77391d6f8 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -206,6 +206,8 @@ enum { NFSPROC4_CLNT_READ, NFSPROC4_CLNT_WRITE, NFSPROC4_CLNT_COMMIT, + NFSPROC4_CLNT_OPEN, + NFSPROC4_CLNT_OPEN_CONFIRM, }; #endif diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index bc44563921f7..7d53fd8a8710 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -155,6 +155,13 @@ struct nfs_inode { wait_queue_head_t nfs_i_wait; +#ifdef CONFIG_NFS_V4 + /* NFSv4 state */ + struct nfs4_shareowner *ro_owner; + struct nfs4_shareowner *wo_owner; + struct nfs4_shareowner *rw_owner; +#endif /* CONFIG_NFS_V4*/ + struct inode vfs_inode; }; @@ -435,28 +442,74 @@ extern void * nfs_root_data(void); #define NFS_JUKEBOX_RETRY_TIME (5 * HZ) #ifdef CONFIG_NFS_V4 + +/* + * In a seqid-mutating op, this macro controls which error return + * values trigger incrementation of the seqid. + * + * from rfc 3010: + * The client MUST monotonically increment the sequence number for the + * CLOSE, LOCK, LOCKU, OPEN, OPEN_CONFIRM, and OPEN_DOWNGRADE + * operations. This is true even in the event that the previous + * operation that used the sequence number received an error. The only + * exception to this rule is if the previous operation received one of + * the following errors: NFSERR_STALE_CLIENTID, NFSERR_STALE_STATEID, + * NFSERR_BAD_STATEID, NFSERR_BAD_SEQID, NFSERR_BADXDR, + * NFSERR_RESOURCE, NFSERR_NOFILEHANDLE. + * + */ +#define seqid_mutating_err(err) \ +(((err) != NFSERR_STALE_CLIENTID) && \ + ((err) != NFSERR_STALE_STATEID) && \ + ((err) != NFSERR_BAD_STATEID) && \ + ((err) != NFSERR_BAD_SEQID) && \ + ((err) != NFSERR_BAD_XDR) && \ + ((err) != NFSERR_RESOURCE) && \ + ((err) != NFSERR_NOFILEHANDLE)) + struct nfs4_client { - atomic_t cl_count; /* refcount */ u64 cl_clientid; /* constant */ - nfs4_verifier cl_confirm; + nfs4_verifier cl_confirm; - /* - * Starts a list of lockowners, linked through lo_list. - */ - struct list_head cl_lockowners; /* protected by state_spinlock */ + u32 cl_lockowner_id; +}; + +/* +* The ->so_sema is held during all shareowner seqid-mutating operations: +* OPEN, OPEN_DOWNGRADE, and CLOSE. +* Its purpose is to properly serialize so_seqid, as mandated by +* the protocol. +*/ +struct nfs4_shareowner { + u32 so_id; /* 32-bit identifier, unique */ + struct semaphore so_sema; + u32 so_seqid; /* protected by so_sema */ + nfs4_stateid so_stateid; /* protected by so_sema */ + unsigned int so_flags; /* protected by so_sema */ }; + /* nfs4proc.c */ extern int nfs4_proc_renew(struct nfs_server *server); /* nfs4renewd.c */ extern int nfs4_init_renewd(struct nfs_server *server); -#endif /* CONFIG_NFS_V4 */ - -#ifdef CONFIG_NFS_V4 +/* nfs4state.c */ extern struct nfs4_client *nfs4_get_client(void); extern void nfs4_put_client(struct nfs4_client *clp); +extern struct nfs4_shareowner * nfs4_get_shareowner(struct inode *inode); +void nfs4_put_shareowner(struct inode *inode, struct nfs4_shareowner *sp); +extern int nfs4_set_inode_share(struct inode * inode, + struct nfs4_shareowner *sp, unsigned int flags); +extern void nfs4_increment_seqid(u32 status, struct nfs4_shareowner *sp); +extern int nfs4_test_shareowner(struct inode *inode, unsigned int open_flags); +struct nfs4_shareowner * nfs4_get_inode_share(struct inode * inode, unsigned int open_flags); + + + + + struct nfs4_mount_data; static inline int @@ -481,6 +534,7 @@ destroy_nfsv4_state(struct nfs_server *server) #else #define create_nfsv4_state(server, data) 0 #define destroy_nfsv4_state(server) do { } while (0) +#define nfs4_put_shareowner(inode, owner) do { } while (0) #endif #endif /* __KERNEL__ */ diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 980705c7307e..2d1544931139 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -88,6 +88,51 @@ struct nfs_pathconf { }; /* + * Arguments to the open call. + */ +struct nfs_openargs { + struct nfs_fh * fh; + __u32 seqid; + __u32 share_access; + __u64 clientid; + __u32 id; + __u32 opentype; + __u32 createmode; + union { + struct iattr * attrs; /* UNCHECKED, GUARDED */ + nfs4_verifier verifier; /* EXCLUSIVE */ + } u; + struct qstr * name; + struct nfs4_getattr * f_getattr; + struct nfs4_getattr * d_getattr; +}; + +struct nfs_openres { + __u32 status; + nfs4_stateid stateid; + struct nfs_fh fh; + struct nfs4_change_info * cinfo; + __u32 rflags; + struct nfs4_getattr * f_getattr; + struct nfs4_getattr * d_getattr; +}; + +/* + * Arguments to the open_confirm call. + */ +struct nfs_open_confirmargs { + struct nfs_fh * fh; + nfs4_stateid stateid; + __u32 seqid; +}; + +struct nfs_open_confirmres { + __u32 status; + nfs4_stateid stateid; +}; + + +/* * Arguments to the read call. */ |
