diff options
Diffstat (limited to 'include/linux/nfsd')
-rw-r--r-- | include/linux/nfsd/auth.h | 27 | ||||
-rw-r--r-- | include/linux/nfsd/cache.h | 81 | ||||
-rw-r--r-- | include/linux/nfsd/const.h | 45 | ||||
-rw-r--r-- | include/linux/nfsd/debug.h | 48 | ||||
-rw-r--r-- | include/linux/nfsd/export.h | 137 | ||||
-rw-r--r-- | include/linux/nfsd/interface.h | 13 | ||||
-rw-r--r-- | include/linux/nfsd/nfsd.h | 311 | ||||
-rw-r--r-- | include/linux/nfsd/nfsfh.h | 343 | ||||
-rw-r--r-- | include/linux/nfsd/state.h | 298 | ||||
-rw-r--r-- | include/linux/nfsd/stats.h | 44 | ||||
-rw-r--r-- | include/linux/nfsd/syscall.h | 125 | ||||
-rw-r--r-- | include/linux/nfsd/xdr.h | 172 | ||||
-rw-r--r-- | include/linux/nfsd/xdr3.h | 321 | ||||
-rw-r--r-- | include/linux/nfsd/xdr4.h | 463 |
14 files changed, 2428 insertions, 0 deletions
diff --git a/include/linux/nfsd/auth.h b/include/linux/nfsd/auth.h new file mode 100644 index 000000000000..0fb9f7212195 --- /dev/null +++ b/include/linux/nfsd/auth.h @@ -0,0 +1,27 @@ +/* + * include/linux/nfsd/auth.h + * + * nfsd-specific authentication stuff. + * uid/gid mapping not yet implemented. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef LINUX_NFSD_AUTH_H +#define LINUX_NFSD_AUTH_H + +#ifdef __KERNEL__ + +#define nfsd_luid(rq, uid) ((u32)(uid)) +#define nfsd_lgid(rq, gid) ((u32)(gid)) +#define nfsd_ruid(rq, uid) ((u32)(uid)) +#define nfsd_rgid(rq, gid) ((u32)(gid)) + +/* + * Set the current process's fsuid/fsgid etc to those of the NFS + * client user + */ +int nfsd_setuser(struct svc_rqst *, struct svc_export *); + +#endif /* __KERNEL__ */ +#endif /* LINUX_NFSD_AUTH_H */ diff --git a/include/linux/nfsd/cache.h b/include/linux/nfsd/cache.h new file mode 100644 index 000000000000..c3a3557c2a5b --- /dev/null +++ b/include/linux/nfsd/cache.h @@ -0,0 +1,81 @@ +/* + * include/linux/nfsd/cache.h + * + * Request reply cache. This was heavily inspired by the + * implementation in 4.3BSD/4.4BSD. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef NFSCACHE_H +#define NFSCACHE_H + +#ifdef __KERNEL__ +#include <linux/in.h> +#include <linux/uio.h> + +/* + * Representation of a reply cache entry. The first two members *must* + * be hash_next and hash_prev. + */ +struct svc_cacherep { + struct hlist_node c_hash; + struct list_head c_lru; + + unsigned char c_state, /* unused, inprog, done */ + c_type, /* status, buffer */ + c_secure : 1; /* req came from port < 1024 */ + struct sockaddr_in c_addr; + u32 c_xid; + u32 c_prot; + u32 c_proc; + u32 c_vers; + unsigned long c_timestamp; + union { + struct kvec u_vec; + u32 u_status; + } c_u; +}; + +#define c_replvec c_u.u_vec +#define c_replstat c_u.u_status + +/* cache entry states */ +enum { + RC_UNUSED, + RC_INPROG, + RC_DONE +}; + +/* return values */ +enum { + RC_DROPIT, + RC_REPLY, + RC_DOIT, + RC_INTR +}; + +/* + * Cache types. + * We may want to add more types one day, e.g. for diropres and + * attrstat replies. Using cache entries with fixed length instead + * of buffer pointers may be more efficient. + */ +enum { + RC_NOCACHE, + RC_REPLSTAT, + RC_REPLBUFF, +}; + +/* + * If requests are retransmitted within this interval, they're dropped. + */ +#define RC_DELAY (HZ/5) + +void nfsd_cache_init(void); +void nfsd_cache_shutdown(void); +int nfsd_cache_lookup(struct svc_rqst *, int); +void nfsd_cache_update(struct svc_rqst *, int, u32 *); + +#endif /* __KERNEL__ */ +#endif /* NFSCACHE_H */ diff --git a/include/linux/nfsd/const.h b/include/linux/nfsd/const.h new file mode 100644 index 000000000000..b75bb1b38d09 --- /dev/null +++ b/include/linux/nfsd/const.h @@ -0,0 +1,45 @@ +/* + * include/linux/nfsd/const.h + * + * Various constants related to NFS. + * + * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef _LINUX_NFSD_CONST_H +#define _LINUX_NFSD_CONST_H + +#include <linux/nfs.h> +#include <linux/nfs2.h> +#include <linux/nfs3.h> +#include <linux/nfs4.h> + +/* + * Maximum protocol version supported by knfsd + */ +#define NFSSVC_MAXVERS 3 + +/* + * Maximum blocksize supported by daemon currently at 32K + */ +#define NFSSVC_MAXBLKSIZE (32*1024) + +#ifdef __KERNEL__ + +#ifndef NFS_SUPER_MAGIC +# define NFS_SUPER_MAGIC 0x6969 +#endif + +#define NFSD_BUFSIZE (1024 + NFSSVC_MAXBLKSIZE) + +#ifdef CONFIG_NFSD_V4 +# define NFSSVC_XDRSIZE NFS4_SVC_XDRSIZE +#elif defined(CONFIG_NFSD_V3) +# define NFSSVC_XDRSIZE NFS3_SVC_XDRSIZE +#else +# define NFSSVC_XDRSIZE NFS2_SVC_XDRSIZE +#endif + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_NFSD_CONST_H */ diff --git a/include/linux/nfsd/debug.h b/include/linux/nfsd/debug.h new file mode 100644 index 000000000000..ee4aa91788e7 --- /dev/null +++ b/include/linux/nfsd/debug.h @@ -0,0 +1,48 @@ +/* + * linux/include/linux/nfsd/debug.h + * + * Debugging-related stuff for nfsd + * + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef LINUX_NFSD_DEBUG_H +#define LINUX_NFSD_DEBUG_H + +#include <linux/sunrpc/debug.h> + +/* + * Enable debugging for nfsd. + * Requires RPC_DEBUG. + */ +#ifdef RPC_DEBUG +# define NFSD_DEBUG 1 +#endif + +/* + * knfsd debug flags + */ +#define NFSDDBG_SOCK 0x0001 +#define NFSDDBG_FH 0x0002 +#define NFSDDBG_EXPORT 0x0004 +#define NFSDDBG_SVC 0x0008 +#define NFSDDBG_PROC 0x0010 +#define NFSDDBG_FILEOP 0x0020 +#define NFSDDBG_AUTH 0x0040 +#define NFSDDBG_REPCACHE 0x0080 +#define NFSDDBG_XDR 0x0100 +#define NFSDDBG_LOCKD 0x0200 +#define NFSDDBG_ALL 0x7FFF +#define NFSDDBG_NOCHANGE 0xFFFF + + +#ifdef __KERNEL__ +# undef ifdebug +# ifdef NFSD_DEBUG +# define ifdebug(flag) if (nfsd_debug & NFSDDBG_##flag) +# else +# define ifdebug(flag) if (0) +# endif +#endif /* __KERNEL__ */ + +#endif /* LINUX_NFSD_DEBUG_H */ diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h new file mode 100644 index 000000000000..6bad4766d3d9 --- /dev/null +++ b/include/linux/nfsd/export.h @@ -0,0 +1,137 @@ +/* + * include/linux/nfsd/export.h + * + * Public declarations for NFS exports. The definitions for the + * syscall interface are in nfsctl.h + * + * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef NFSD_EXPORT_H +#define NFSD_EXPORT_H + +#include <asm/types.h> +#ifdef __KERNEL__ +# include <linux/types.h> +# include <linux/in.h> +#endif + +/* + * Important limits for the exports stuff. + */ +#define NFSCLNT_IDMAX 1024 +#define NFSCLNT_ADDRMAX 16 +#define NFSCLNT_KEYMAX 32 + +/* + * Export flags. + */ +#define NFSEXP_READONLY 0x0001 +#define NFSEXP_INSECURE_PORT 0x0002 +#define NFSEXP_ROOTSQUASH 0x0004 +#define NFSEXP_ALLSQUASH 0x0008 +#define NFSEXP_ASYNC 0x0010 +#define NFSEXP_GATHERED_WRITES 0x0020 +/* 40 80 100 currently unused */ +#define NFSEXP_NOHIDE 0x0200 +#define NFSEXP_NOSUBTREECHECK 0x0400 +#define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */ +#define NFSEXP_MSNFS 0x1000 /* do silly things that MS clients expect */ +#define NFSEXP_FSID 0x2000 +#define NFSEXP_CROSSMOUNT 0x4000 +#define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */ +#define NFSEXP_ALLFLAGS 0xFE3F + + +#ifdef __KERNEL__ + +struct svc_export { + struct cache_head h; + struct auth_domain * ex_client; + int ex_flags; + struct vfsmount * ex_mnt; + struct dentry * ex_dentry; + uid_t ex_anon_uid; + gid_t ex_anon_gid; + int ex_fsid; +}; + +/* an "export key" (expkey) maps a filehandlefragement to an + * svc_export for a given client. There can be two per export, one + * for type 0 (dev/ino), one for type 1 (fsid) + */ +struct svc_expkey { + struct cache_head h; + + struct auth_domain * ek_client; + int ek_fsidtype; + u32 ek_fsid[3]; + + struct svc_export * ek_export; +}; + +#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT)) +#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC)) +#define EX_RDONLY(exp) ((exp)->ex_flags & NFSEXP_READONLY) +#define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE) +#define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES) + + +/* + * Function declarations + */ +void nfsd_export_init(void); +void nfsd_export_shutdown(void); +void nfsd_export_flush(void); +void exp_readlock(void); +void exp_readunlock(void); +struct svc_expkey * exp_find_key(struct auth_domain *clp, + int fsid_type, u32 *fsidv, + struct cache_req *reqp); +struct svc_export * exp_get_by_name(struct auth_domain *clp, + struct vfsmount *mnt, + struct dentry *dentry, + struct cache_req *reqp); +struct svc_export * exp_parent(struct auth_domain *clp, + struct vfsmount *mnt, + struct dentry *dentry, + struct cache_req *reqp); +int exp_rootfh(struct auth_domain *, + char *path, struct knfsd_fh *, int maxsize); +int exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq); +int nfserrno(int errno); + +extern void expkey_put(struct cache_head *item, struct cache_detail *cd); +extern void svc_export_put(struct cache_head *item, struct cache_detail *cd); +extern struct cache_detail svc_export_cache, svc_expkey_cache; + +static inline void exp_put(struct svc_export *exp) +{ + svc_export_put(&exp->h, &svc_export_cache); +} + +static inline void exp_get(struct svc_export *exp) +{ + cache_get(&exp->h); +} +static inline struct svc_export * +exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, + struct cache_req *reqp) +{ + struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); + if (ek && !IS_ERR(ek)) { + struct svc_export *exp = ek->ek_export; + int err; + exp_get(exp); + expkey_put(&ek->h, &svc_expkey_cache); + if ((err = cache_check(&svc_export_cache, &exp->h, reqp))) + exp = ERR_PTR(err); + return exp; + } else + return ERR_PTR(PTR_ERR(ek)); +} + +#endif /* __KERNEL__ */ + +#endif /* NFSD_EXPORT_H */ + diff --git a/include/linux/nfsd/interface.h b/include/linux/nfsd/interface.h new file mode 100644 index 000000000000..af0979704afb --- /dev/null +++ b/include/linux/nfsd/interface.h @@ -0,0 +1,13 @@ +/* + * include/linux/nfsd/interface.h + * + * defines interface between nfsd and other bits of + * the kernel. Particularly filesystems (eventually). + * + * Copyright (C) 2000 Neil Brown <neilb@cse.unsw.edu.au> + */ + +#ifndef LINUX_NFSD_INTERFACE_H +#define LINUX_NFSD_INTERFACE_H + +#endif /* LINUX_NFSD_INTERFACE_H */ diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h new file mode 100644 index 000000000000..8f85d9a59607 --- /dev/null +++ b/include/linux/nfsd/nfsd.h @@ -0,0 +1,311 @@ +/* + * linux/include/linux/nfsd/nfsd.h + * + * Hodge-podge collection of knfsd-related stuff. + * I will sort this out later. + * + * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef LINUX_NFSD_NFSD_H +#define LINUX_NFSD_NFSD_H + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/unistd.h> +#include <linux/dirent.h> +#include <linux/fs.h> +#include <linux/mount.h> + +#include <linux/nfsd/debug.h> +#include <linux/nfsd/nfsfh.h> +#include <linux/nfsd/export.h> +#include <linux/nfsd/auth.h> +#include <linux/nfsd/stats.h> +#include <linux/nfsd/interface.h> +/* + * nfsd version + */ +#define NFSD_VERSION "0.5" +#define NFSD_SUPPORTED_MINOR_VERSION 0 + +#ifdef __KERNEL__ +/* + * Special flags for nfsd_permission. These must be different from MAY_READ, + * MAY_WRITE, and MAY_EXEC. + */ +#define MAY_NOP 0 +#define MAY_SATTR 8 +#define MAY_TRUNC 16 +#define MAY_LOCK 32 +#define MAY_OWNER_OVERRIDE 64 +#define MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/ +#if (MAY_SATTR | MAY_TRUNC | MAY_LOCK | MAY_OWNER_OVERRIDE | MAY_LOCAL_ACCESS) & (MAY_READ | MAY_WRITE | MAY_EXEC) +# error "please use a different value for MAY_SATTR or MAY_TRUNC or MAY_LOCK or MAY_LOCAL_ACCESS or MAY_OWNER_OVERRIDE." +#endif +#define MAY_CREATE (MAY_EXEC|MAY_WRITE) +#define MAY_REMOVE (MAY_EXEC|MAY_WRITE|MAY_TRUNC) + +/* + * Callback function for readdir + */ +struct readdir_cd { + int err; /* 0, nfserr, or nfserr_eof */ +}; +typedef int (*encode_dent_fn)(struct readdir_cd *, const char *, + int, loff_t, ino_t, unsigned int); +typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); + +extern struct svc_program nfsd_program; +extern struct svc_version nfsd_version2, nfsd_version3, + nfsd_version4; + +/* + * Function prototypes. + */ +int nfsd_svc(unsigned short port, int nrservs); +int nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp); + +/* nfsd/vfs.c */ +int fh_lock_parent(struct svc_fh *, struct dentry *); +int nfsd_racache_init(int); +void nfsd_racache_shutdown(void); +int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, + struct svc_export **expp); +int nfsd_lookup(struct svc_rqst *, struct svc_fh *, + const char *, int, struct svc_fh *); +int nfsd_setattr(struct svc_rqst *, struct svc_fh *, + struct iattr *, int, time_t); +#ifdef CONFIG_NFSD_V4 +int nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *, + struct nfs4_acl *); +int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **); +#endif /* CONFIG_NFSD_V4 */ +int nfsd_create(struct svc_rqst *, struct svc_fh *, + char *name, int len, struct iattr *attrs, + int type, dev_t rdev, struct svc_fh *res); +#ifdef CONFIG_NFSD_V3 +int nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *); +int nfsd_create_v3(struct svc_rqst *, struct svc_fh *, + char *name, int len, struct iattr *attrs, + struct svc_fh *res, int createmode, + u32 *verifier, int *truncp); +int nfsd_commit(struct svc_rqst *, struct svc_fh *, + loff_t, unsigned long); +#endif /* CONFIG_NFSD_V3 */ +int nfsd_open(struct svc_rqst *, struct svc_fh *, int, + int, struct file **); +void nfsd_close(struct file *); +int nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *, + loff_t, struct kvec *, int, unsigned long *); +int nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *, + loff_t, struct kvec *,int, unsigned long, int *); +int nfsd_readlink(struct svc_rqst *, struct svc_fh *, + char *, int *); +int nfsd_symlink(struct svc_rqst *, struct svc_fh *, + char *name, int len, char *path, int plen, + struct svc_fh *res, struct iattr *); +int nfsd_link(struct svc_rqst *, struct svc_fh *, + char *, int, struct svc_fh *); +int nfsd_rename(struct svc_rqst *, + struct svc_fh *, char *, int, + struct svc_fh *, char *, int); +int nfsd_remove(struct svc_rqst *, + struct svc_fh *, char *, int); +int nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, + char *name, int len); +int nfsd_truncate(struct svc_rqst *, struct svc_fh *, + unsigned long size); +int nfsd_readdir(struct svc_rqst *, struct svc_fh *, + loff_t *, struct readdir_cd *, encode_dent_fn); +int nfsd_statfs(struct svc_rqst *, struct svc_fh *, + struct kstatfs *); + +int nfsd_notify_change(struct inode *, struct iattr *); +int nfsd_permission(struct svc_export *, struct dentry *, int); + + +/* + * NFSv4 State + */ +#ifdef CONFIG_NFSD_V4 +int nfs4_state_init(void); +void nfs4_state_shutdown(void); +time_t nfs4_lease_time(void); +void nfs4_reset_lease(time_t leasetime); +#else +static inline int nfs4_state_init(void){return 0;} +static inline void nfs4_state_shutdown(void){} +static inline time_t nfs4_lease_time(void){return 0;} +static inline void nfs4_reset_lease(time_t leasetime){} +#endif + +/* + * lockd binding + */ +void nfsd_lockd_init(void); +void nfsd_lockd_shutdown(void); + + +/* + * These macros provide pre-xdr'ed values for faster operation. + */ +#define nfs_ok __constant_htonl(NFS_OK) +#define nfserr_perm __constant_htonl(NFSERR_PERM) +#define nfserr_noent __constant_htonl(NFSERR_NOENT) +#define nfserr_io __constant_htonl(NFSERR_IO) +#define nfserr_nxio __constant_htonl(NFSERR_NXIO) +#define nfserr_eagain __constant_htonl(NFSERR_EAGAIN) +#define nfserr_acces __constant_htonl(NFSERR_ACCES) +#define nfserr_exist __constant_htonl(NFSERR_EXIST) +#define nfserr_xdev __constant_htonl(NFSERR_XDEV) +#define nfserr_nodev __constant_htonl(NFSERR_NODEV) +#define nfserr_notdir __constant_htonl(NFSERR_NOTDIR) +#define nfserr_isdir __constant_htonl(NFSERR_ISDIR) +#define nfserr_inval __constant_htonl(NFSERR_INVAL) +#define nfserr_fbig __constant_htonl(NFSERR_FBIG) +#define nfserr_nospc __constant_htonl(NFSERR_NOSPC) +#define nfserr_rofs __constant_htonl(NFSERR_ROFS) +#define nfserr_mlink __constant_htonl(NFSERR_MLINK) +#define nfserr_opnotsupp __constant_htonl(NFSERR_OPNOTSUPP) +#define nfserr_nametoolong __constant_htonl(NFSERR_NAMETOOLONG) +#define nfserr_notempty __constant_htonl(NFSERR_NOTEMPTY) +#define nfserr_dquot __constant_htonl(NFSERR_DQUOT) +#define nfserr_stale __constant_htonl(NFSERR_STALE) +#define nfserr_remote __constant_htonl(NFSERR_REMOTE) +#define nfserr_wflush __constant_htonl(NFSERR_WFLUSH) +#define nfserr_badhandle __constant_htonl(NFSERR_BADHANDLE) +#define nfserr_notsync __constant_htonl(NFSERR_NOT_SYNC) +#define nfserr_badcookie __constant_htonl(NFSERR_BAD_COOKIE) +#define nfserr_notsupp __constant_htonl(NFSERR_NOTSUPP) +#define nfserr_toosmall __constant_htonl(NFSERR_TOOSMALL) +#define nfserr_serverfault __constant_htonl(NFSERR_SERVERFAULT) +#define nfserr_badtype __constant_htonl(NFSERR_BADTYPE) +#define nfserr_jukebox __constant_htonl(NFSERR_JUKEBOX) +#define nfserr_denied __constant_htonl(NFSERR_DENIED) +#define nfserr_deadlock __constant_htonl(NFSERR_DEADLOCK) +#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) +#define nfserr_stale_clientid __constant_htonl(NFSERR_STALE_CLIENTID) +#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_restorefh __constant_htonl(NFSERR_RESTOREFH) +#define nfserr_attrnotsupp __constant_htonl(NFSERR_ATTRNOTSUPP) +#define nfserr_bad_xdr __constant_htonl(NFSERR_BAD_XDR) +#define nfserr_openmode __constant_htonl(NFSERR_OPENMODE) +#define nfserr_locks_held __constant_htonl(NFSERR_LOCKS_HELD) +#define nfserr_op_illegal __constant_htonl(NFSERR_OP_ILLEGAL) +#define nfserr_grace __constant_htonl(NFSERR_GRACE) +#define nfserr_no_grace __constant_htonl(NFSERR_NO_GRACE) +#define nfserr_reclaim_bad __constant_htonl(NFSERR_RECLAIM_BAD) +#define nfserr_badname __constant_htonl(NFSERR_BADNAME) +#define nfserr_cb_path_down __constant_htonl(NFSERR_CB_PATH_DOWN) + +/* error codes for internal use */ +/* if a request fails due to kmalloc failure, it gets dropped. + * Client should resend eventually + */ +#define nfserr_dropit __constant_htonl(30000) +/* end-of-file indicator in readdir */ +#define nfserr_eof __constant_htonl(30001) + +/* Check for dir entries '.' and '..' */ +#define isdotent(n, l) (l < 3 && n[0] == '.' && (l == 1 || n[1] == '.')) + +/* + * Time of server startup + */ +extern struct timeval nfssvc_boot; + +static inline int is_fsid(struct svc_fh *fh, struct knfsd_fh *reffh) +{ + if (fh->fh_export->ex_flags & NFSEXP_FSID) { + struct vfsmount *mnt = fh->fh_export->ex_mnt; + if (!old_valid_dev(mnt->mnt_sb->s_dev) || + (reffh->fh_version == 1 && reffh->fh_fsid_type == 1)) + return 1; + } + return 0; +} + + +#ifdef CONFIG_NFSD_V4 + +/* before processing a COMPOUND operation, we have to check that there + * is enough space in the buffer for XDR encode to succeed. otherwise, + * we might process an operation with side effects, and be unable to + * tell the client that the operation succeeded. + * + * COMPOUND_SLACK_SPACE - this is the minimum amount of buffer space + * needed to encode an "ordinary" _successful_ operation. (GETATTR, + * READ, READDIR, and READLINK have their own buffer checks.) if we + * fall below this level, we fail the next operation with NFS4ERR_RESOURCE. + * + * COMPOUND_ERR_SLACK_SPACE - this is the minimum amount of buffer space + * needed to encode an operation which has failed with NFS4ERR_RESOURCE. + * care is taken to ensure that we never fall below this level for any + * reason. + */ +#define COMPOUND_SLACK_SPACE 140 /* OP_GETFH */ +#define COMPOUND_ERR_SLACK_SPACE 12 /* OP_SETATTR */ + +#define NFSD_LEASE_TIME (nfs4_lease_time()) +#define NFSD_LAUNDROMAT_MINTIMEOUT 10 /* seconds */ + +/* + * The following attributes are currently not supported by the NFSv4 server: + * ARCHIVE (deprecated anyway) + * FS_LOCATIONS (will be supported eventually) + * HIDDEN (unlikely to be supported any time soon) + * MIMETYPE (unlikely to be supported any time soon) + * QUOTA_* (will be supported in a forthcoming patch) + * SYSTEM (unlikely to be supported any time soon) + * TIME_BACKUP (unlikely to be supported any time soon) + * TIME_CREATE (unlikely to be supported any time soon) + */ +#define NFSD_SUPPORTED_ATTRS_WORD0 \ +(FATTR4_WORD0_SUPPORTED_ATTRS | FATTR4_WORD0_TYPE | FATTR4_WORD0_FH_EXPIRE_TYPE \ + | FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE | FATTR4_WORD0_LINK_SUPPORT \ + | FATTR4_WORD0_SYMLINK_SUPPORT | FATTR4_WORD0_NAMED_ATTR | FATTR4_WORD0_FSID \ + | FATTR4_WORD0_UNIQUE_HANDLES | FATTR4_WORD0_LEASE_TIME | FATTR4_WORD0_RDATTR_ERROR \ + | FATTR4_WORD0_ACLSUPPORT | FATTR4_WORD0_CANSETTIME | FATTR4_WORD0_CASE_INSENSITIVE \ + | FATTR4_WORD0_CASE_PRESERVING | FATTR4_WORD0_CHOWN_RESTRICTED \ + | FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FILEID | FATTR4_WORD0_FILES_AVAIL \ + | FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_HOMOGENEOUS \ + | FATTR4_WORD0_MAXFILESIZE | FATTR4_WORD0_MAXLINK | FATTR4_WORD0_MAXNAME \ + | FATTR4_WORD0_MAXREAD | FATTR4_WORD0_MAXWRITE | FATTR4_WORD0_ACL) + +#define NFSD_SUPPORTED_ATTRS_WORD1 \ +(FATTR4_WORD1_MODE | FATTR4_WORD1_NO_TRUNC | FATTR4_WORD1_NUMLINKS \ + | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP | FATTR4_WORD1_RAWDEV \ + | FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL \ + | FATTR4_WORD1_SPACE_USED | FATTR4_WORD1_TIME_ACCESS | FATTR4_WORD1_TIME_ACCESS_SET \ + | FATTR4_WORD1_TIME_DELTA | FATTR4_WORD1_TIME_METADATA \ + | FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID) + +/* These will return ERR_INVAL if specified in GETATTR or READDIR. */ +#define NFSD_WRITEONLY_ATTRS_WORD1 \ +(FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) + +/* These are the only attrs allowed in CREATE/OPEN/SETATTR. */ +#define NFSD_WRITEABLE_ATTRS_WORD0 \ +(FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL ) +#define NFSD_WRITEABLE_ATTRS_WORD1 \ +(FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ + | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY_SET) + +#endif /* CONFIG_NFSD_V4 */ + +#endif /* __KERNEL__ */ + +#endif /* LINUX_NFSD_NFSD_H */ diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h new file mode 100644 index 000000000000..bb842ea41033 --- /dev/null +++ b/include/linux/nfsd/nfsfh.h @@ -0,0 +1,343 @@ +/* + * include/linux/nfsd/nfsfh.h + * + * This file describes the layout of the file handles as passed + * over the wire. + * + * Earlier versions of knfsd used to sign file handles using keyed MD5 + * or SHA. I've removed this code, because it doesn't give you more + * security than blocking external access to port 2049 on your firewall. + * + * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef _LINUX_NFSD_FH_H +#define _LINUX_NFSD_FH_H + +#include <asm/types.h> +#ifdef __KERNEL__ +# include <linux/config.h> +# include <linux/types.h> +# include <linux/string.h> +# include <linux/fs.h> +#endif +#include <linux/nfsd/const.h> +#include <linux/nfsd/debug.h> + +/* + * This is the old "dentry style" Linux NFSv2 file handle. + * + * The xino and xdev fields are currently used to transport the + * ino/dev of the exported inode. + */ +struct nfs_fhbase_old { + __u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */ + __u32 fb_ino; /* our inode number */ + __u32 fb_dirino; /* dir inode number, 0 for directories */ + __u32 fb_dev; /* our device */ + __u32 fb_xdev; + __u32 fb_xino; + __u32 fb_generation; +}; + +/* + * This is the new flexible, extensible style NFSv2/v3 file handle. + * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000 + * + * The file handle is seens as a list of 4byte words. + * The first word contains a version number (1) and four descriptor bytes + * that tell how the remaining 3 variable length fields should be handled. + * These three bytes are auth_type, fsid_type and fileid_type. + * + * All 4byte values are in host-byte-order. + * + * The auth_type field specifies how the filehandle can be authenticated + * This might allow a file to be confirmed to be in a writable part of a + * filetree without checking the path from it upto the root. + * Current values: + * 0 - No authentication. fb_auth is 0 bytes long + * Possible future values: + * 1 - 4 bytes taken from MD5 hash of the remainer of the file handle + * prefixed by a secret and with the important export flags. + * + * The fsid_type identifies how the filesystem (or export point) is + * encoded. + * Current values: + * 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number + * NOTE: we cannot use the kdev_t device id value, because kdev_t.h + * says we mustn't. We must break it up and reassemble. + * 1 - 4 byte user specified identifier + * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED + * 3 - 4 byte device id, encoded for user-space, 4 byte inode number + * + * The fileid_type identified how the file within the filesystem is encoded. + * This is (will be) passed to, and set by, the underlying filesystem if it supports + * filehandle operations. The filesystem must not use the value '0' or '0xff' and may + * only use the values 1 and 2 as defined below: + * Current values: + * 0 - The root, or export point, of the filesystem. fb_fileid is 0 bytes. + * 1 - 32bit inode number, 32 bit generation number. + * 2 - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number. + * + */ +struct nfs_fhbase_new { + __u8 fb_version; /* == 1, even => nfs_fhbase_old */ + __u8 fb_auth_type; + __u8 fb_fsid_type; + __u8 fb_fileid_type; + __u32 fb_auth[1]; +/* __u32 fb_fsid[0]; floating */ +/* __u32 fb_fileid[0]; floating */ +}; + +struct knfsd_fh { + unsigned int fh_size; /* significant for NFSv3. + * Points to the current size while building + * a new file handle + */ + union { + struct nfs_fhbase_old fh_old; + __u32 fh_pad[NFS4_FHSIZE/4]; + struct nfs_fhbase_new fh_new; + } fh_base; +}; + +#define ofh_dcookie fh_base.fh_old.fb_dcookie +#define ofh_ino fh_base.fh_old.fb_ino +#define ofh_dirino fh_base.fh_old.fb_dirino +#define ofh_dev fh_base.fh_old.fb_dev +#define ofh_xdev fh_base.fh_old.fb_xdev +#define ofh_xino fh_base.fh_old.fb_xino +#define ofh_generation fh_base.fh_old.fb_generation + +#define fh_version fh_base.fh_new.fb_version +#define fh_fsid_type fh_base.fh_new.fb_fsid_type +#define fh_auth_type fh_base.fh_new.fb_auth_type +#define fh_fileid_type fh_base.fh_new.fb_fileid_type +#define fh_auth fh_base.fh_new.fb_auth +#define fh_fsid fh_base.fh_new.fb_auth + +#ifdef __KERNEL__ + +static inline __u32 ino_t_to_u32(ino_t ino) +{ + return (__u32) ino; +} + +static inline ino_t u32_to_ino_t(__u32 uino) +{ + return (ino_t) uino; +} + +/* + * This is the internal representation of an NFS handle used in knfsd. + * pre_mtime/post_version will be used to support wcc_attr's in NFSv3. + */ +typedef struct svc_fh { + struct knfsd_fh fh_handle; /* FH data */ + struct dentry * fh_dentry; /* validated dentry */ + struct svc_export * fh_export; /* export pointer */ + int fh_maxsize; /* max size for fh_handle */ + + unsigned char fh_locked; /* inode locked by us */ + +#ifdef CONFIG_NFSD_V3 + unsigned char fh_post_saved; /* post-op attrs saved */ + unsigned char fh_pre_saved; /* pre-op attrs saved */ + + /* Pre-op attributes saved during fh_lock */ + __u64 fh_pre_size; /* size before operation */ + struct timespec fh_pre_mtime; /* mtime before oper */ + struct timespec fh_pre_ctime; /* ctime before oper */ + + /* Post-op attributes saved in fh_unlock */ + umode_t fh_post_mode; /* i_mode */ + nlink_t fh_post_nlink; /* i_nlink */ + uid_t fh_post_uid; /* i_uid */ + gid_t fh_post_gid; /* i_gid */ + __u64 fh_post_size; /* i_size */ + unsigned long fh_post_blocks; /* i_blocks */ + unsigned long fh_post_blksize;/* i_blksize */ + __u32 fh_post_rdev[2];/* i_rdev */ + struct timespec fh_post_atime; /* i_atime */ + struct timespec fh_post_mtime; /* i_mtime */ + struct timespec fh_post_ctime; /* i_ctime */ +#endif /* CONFIG_NFSD_V3 */ + +} svc_fh; + +static inline void mk_fsid_v0(u32 *fsidv, dev_t dev, ino_t ino) +{ + fsidv[0] = htonl((MAJOR(dev)<<16) | + MINOR(dev)); + fsidv[1] = ino_t_to_u32(ino); +} + +static inline void mk_fsid_v1(u32 *fsidv, u32 fsid) +{ + fsidv[0] = fsid; +} + +static inline void mk_fsid_v2(u32 *fsidv, dev_t dev, ino_t ino) +{ + fsidv[0] = htonl(MAJOR(dev)); + fsidv[1] = htonl(MINOR(dev)); + fsidv[2] = ino_t_to_u32(ino); +} + +static inline void mk_fsid_v3(u32 *fsidv, dev_t dev, ino_t ino) +{ + fsidv[0] = new_encode_dev(dev); + fsidv[1] = ino_t_to_u32(ino); +} + +static inline int key_len(int type) +{ + switch(type) { + case 0: return 8; + case 1: return 4; + case 2: return 12; + case 3: return 8; + default: return 0; + } +} + +/* + * Shorthand for dprintk()'s + */ +extern char * SVCFH_fmt(struct svc_fh *fhp); + +/* + * Function prototypes + */ +u32 fh_verify(struct svc_rqst *, struct svc_fh *, int, int); +int fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *); +int fh_update(struct svc_fh *); +void fh_put(struct svc_fh *); + +static __inline__ struct svc_fh * +fh_copy(struct svc_fh *dst, struct svc_fh *src) +{ + if (src->fh_dentry || src->fh_locked) { + struct dentry *dentry = src->fh_dentry; + printk(KERN_ERR "fh_copy: copying %s/%s, already verified!\n", + dentry->d_parent->d_name.name, dentry->d_name.name); + } + + *dst = *src; + return dst; +} + +static __inline__ struct svc_fh * +fh_init(struct svc_fh *fhp, int maxsize) +{ + memset(fhp, 0, sizeof(*fhp)); + fhp->fh_maxsize = maxsize; + return fhp; +} + +#ifdef CONFIG_NFSD_V3 +/* + * Fill in the pre_op attr for the wcc data + */ +static inline void +fill_pre_wcc(struct svc_fh *fhp) +{ + struct inode *inode; + + inode = fhp->fh_dentry->d_inode; + if (!fhp->fh_pre_saved) { + fhp->fh_pre_mtime = inode->i_mtime; + fhp->fh_pre_ctime = inode->i_ctime; + fhp->fh_pre_size = inode->i_size; + fhp->fh_pre_saved = 1; + } +} + +/* + * Fill in the post_op attr for the wcc data + */ +static inline void +fill_post_wcc(struct svc_fh *fhp) +{ + struct inode *inode = fhp->fh_dentry->d_inode; + + if (fhp->fh_post_saved) + printk("nfsd: inode locked twice during operation.\n"); + + fhp->fh_post_mode = inode->i_mode; + fhp->fh_post_nlink = inode->i_nlink; + fhp->fh_post_uid = inode->i_uid; + fhp->fh_post_gid = inode->i_gid; + fhp->fh_post_size = inode->i_size; + if (inode->i_blksize) { + fhp->fh_post_blksize = inode->i_blksize; + fhp->fh_post_blocks = inode->i_blocks; + } else { + fhp->fh_post_blksize = BLOCK_SIZE; + /* how much do we care for accuracy with MinixFS? */ + fhp->fh_post_blocks = (inode->i_size+511) >> 9; + } + fhp->fh_post_rdev[0] = htonl((u32)imajor(inode)); + fhp->fh_post_rdev[1] = htonl((u32)iminor(inode)); + fhp->fh_post_atime = inode->i_atime; + fhp->fh_post_mtime = inode->i_mtime; + fhp->fh_post_ctime = inode->i_ctime; + fhp->fh_post_saved = 1; +} +#else +#define fill_pre_wcc(ignored) +#define fill_post_wcc(notused) +#endif /* CONFIG_NFSD_V3 */ + + +/* + * Lock a file handle/inode + * NOTE: both fh_lock and fh_unlock are done "by hand" in + * vfs.c:nfsd_rename as it needs to grab 2 i_sem's at once + * so, any changes here should be reflected there. + */ +static inline void +fh_lock(struct svc_fh *fhp) +{ + struct dentry *dentry = fhp->fh_dentry; + struct inode *inode; + + dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n", + SVCFH_fmt(fhp), fhp->fh_locked); + + if (!fhp->fh_dentry) { + printk(KERN_ERR "fh_lock: fh not verified!\n"); + return; + } + if (fhp->fh_locked) { + printk(KERN_WARNING "fh_lock: %s/%s already locked!\n", + dentry->d_parent->d_name.name, dentry->d_name.name); + return; + } + + inode = dentry->d_inode; + down(&inode->i_sem); + fill_pre_wcc(fhp); + fhp->fh_locked = 1; +} + +/* + * Unlock a file handle/inode + */ +static inline void +fh_unlock(struct svc_fh *fhp) +{ + if (!fhp->fh_dentry) + printk(KERN_ERR "fh_unlock: fh not verified!\n"); + + if (fhp->fh_locked) { + fill_post_wcc(fhp); + up(&fhp->fh_dentry->d_inode->i_sem); + fhp->fh_locked = 0; + } +} +#endif /* __KERNEL__ */ + + +#endif /* _LINUX_NFSD_FH_H */ diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h new file mode 100644 index 000000000000..b6b2fe1e7c63 --- /dev/null +++ b/include/linux/nfsd/state.h @@ -0,0 +1,298 @@ +/* + * linux/include/nfsd/state.h + * + * Copyright (c) 2001 The Regents of the University of Michigan. + * All rights reserved. + * + * Kendrick Smith <kmsmith@umich.edu> + * Andy Adamson <andros@umich.edu> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _NFSD4_STATE_H +#define _NFSD4_STATE_H + +#include <linux/list.h> +#include <linux/kref.h> +#include <linux/sunrpc/clnt.h> + +#define NFS4_OPAQUE_LIMIT 1024 +typedef struct { + u32 cl_boot; + u32 cl_id; +} clientid_t; + +typedef struct { + u32 so_boot; + u32 so_stateownerid; + u32 so_fileid; +} stateid_opaque_t; + +typedef struct { + u32 si_generation; + stateid_opaque_t si_opaque; +} stateid_t; +#define si_boot si_opaque.so_boot +#define si_stateownerid si_opaque.so_stateownerid +#define si_fileid si_opaque.so_fileid + +extern stateid_t zerostateid; +extern stateid_t onestateid; + +#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t))) +#define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t))) + +struct nfs4_cb_recall { + u32 cbr_ident; + int cbr_trunc; + stateid_t cbr_stateid; + u32 cbr_fhlen; + u32 cbr_fhval[NFS4_FHSIZE]; + struct nfs4_delegation *cbr_dp; +}; + +struct nfs4_delegation { + struct list_head dl_del_perfile; /* nfs4_file->fi_del_perfile */ + struct list_head dl_del_perclnt; /* nfs4_client->cl_del_perclnt*/ + struct list_head dl_recall_lru; /* delegation recalled */ + atomic_t dl_count; /* ref count */ + struct nfs4_client *dl_client; + struct nfs4_file *dl_file; + struct file_lock *dl_flock; + struct file *dl_vfs_file; + u32 dl_type; + time_t dl_time; + struct nfs4_cb_recall dl_recall; +}; + +#define dl_stateid dl_recall.cbr_stateid +#define dl_fhlen dl_recall.cbr_fhlen +#define dl_fhval dl_recall.cbr_fhval + +/* client delegation callback info */ +struct nfs4_callback { + /* SETCLIENTID info */ + u32 cb_parsed; /* addr parsed */ + u32 cb_addr; + unsigned short cb_port; + u32 cb_prog; + u32 cb_ident; + /* RPC client info */ + atomic_t cb_set; /* successful CB_NULL call */ + struct rpc_program cb_program; + struct rpc_stat cb_stat; + struct rpc_clnt * cb_client; +}; + +/* + * struct nfs4_client - one per client. Clientids live here. + * o Each nfs4_client is hashed by clientid. + * + * 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 list_head cl_del_perclnt; /* list: delegations */ + struct list_head cl_lru; /* tail queue */ + struct xdr_netobj cl_name; /* id generated by client */ + nfs4_verifier cl_verifier; /* generated by client */ + time_t cl_time; /* time of last lease renewal */ + u32 cl_addr; /* client ipaddress */ + struct svc_cred cl_cred; /* setclientid principal */ + clientid_t cl_clientid; /* generated by server */ + nfs4_verifier cl_confirm; /* generated by server */ + struct nfs4_callback cl_callback; /* callback info */ + atomic_t cl_count; /* ref count */ +}; + +/* struct nfs4_client_reset + * one per old client. Populates reset_str_hashtbl. Filled from conf_id_hashtbl + * upon lease reset, or from upcall to state_daemon (to read in state + * from non-volitile storage) upon reboot. + */ +struct nfs4_client_reclaim { + struct list_head cr_strhash; /* hash by cr_name */ + struct xdr_netobj cr_name; /* id generated by client */ +}; + +static inline void +update_stateid(stateid_t *stateid) +{ + stateid->si_generation++; +} + +/* A reasonable value for REPLAY_ISIZE was estimated as follows: + * The OPEN response, typically the largest, requires + * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + 8(verifier) + + * 4(deleg. type) + 8(deleg. stateid) + 4(deleg. recall flag) + + * 20(deleg. space limit) + ~32(deleg. ace) = 112 bytes + */ + +#define NFSD4_REPLAY_ISIZE 112 + +/* + * Replay buffer, where the result of the last seqid-mutating operation + * is cached. + */ +struct nfs4_replay { + u32 rp_status; + unsigned int rp_buflen; + char *rp_buf; + unsigned intrp_allocated; + int rp_openfh_len; + char rp_openfh[NFS4_FHSIZE]; + char rp_ibuf[NFSD4_REPLAY_ISIZE]; +}; + +/* +* nfs4_stateowner can either be an open_owner, or a lock_owner +* +* so_idhash: stateid_hashtbl[] for open owner, lockstateid_hashtbl[] +* for lock_owner +* so_strhash: ownerstr_hashtbl[] for open_owner, lock_ownerstr_hashtbl[] +* for lock_owner +* so_perclient: nfs4_client->cl_perclient entry - used when nfs4_client +* struct is reaped. +* so_perfilestate: heads the list of nfs4_stateid (either open or lock) +* and is used to ensure no dangling nfs4_stateid references when we +* release a stateowner. +* so_perlockowner: (open) nfs4_stateid->st_perlockowner entry - used when +* close is called to reap associated byte-range locks +* so_close_lru: (open) stateowner is placed on this list instead of being +* reaped (when so_perfilestate is empty) to hold the last close replay. +* reaped by laundramat thread after lease period. +*/ +struct nfs4_stateowner { + struct kref so_ref; + struct list_head so_idhash; /* hash by so_id */ + struct list_head so_strhash; /* hash by op_name */ + struct list_head so_perclient; /* nfs4_client->cl_perclient */ + struct list_head so_perfilestate; /* list: nfs4_stateid */ + struct list_head so_perlockowner; /* nfs4_stateid->st_perlockowner */ + struct list_head so_close_lru; /* tail queue */ + time_t so_time; /* time of placement on so_close_lru */ + int so_is_open_owner; /* 1=openowner,0=lockowner */ + 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? */ + struct nfs4_replay so_replay; +}; + +/* +* 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 "struct inode *" */ + struct list_head fi_perfile; /* list: nfs4_stateid */ + struct list_head fi_del_perfile; /* list: nfs4_delegation */ + struct inode *fi_inode; + u32 fi_id; /* used with stateowner->so_id + * for stateid_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 +* +* st_hash: stateid_hashtbl[] entry or lockstateid_hashtbl entry +* st_perfile: file_hashtbl[] entry. +* st_perfile_state: nfs4_stateowner->so_perfilestate +* st_perlockowner: (open stateid) list of lock nfs4_stateowners +* st_access_bmap: used only for open stateid +* st_deny_bmap: used only for open stateid +*/ + +struct nfs4_stateid { + struct list_head st_hash; + struct list_head st_perfile; + struct list_head st_perfilestate; + struct list_head st_perlockowner; + struct nfs4_stateowner * st_stateowner; + struct nfs4_file * st_file; + stateid_t st_stateid; + struct file * st_vfs_file; + unsigned long st_access_bmap; + unsigned long st_deny_bmap; +}; + +/* flags for preprocess_seqid_op() */ +#define CHECK_FH 0x00000001 +#define CONFIRM 0x00000002 +#define OPEN_STATE 0x00000004 +#define LOCK_STATE 0x00000008 +#define RD_STATE 0x00000010 +#define WR_STATE 0x00000020 +#define CLOSE_STATE 0x00000040 +#define DELEG_RET 0x00000080 + +#define seqid_mutating_err(err) \ + (((err) != nfserr_stale_clientid) && \ + ((err) != nfserr_bad_seqid) && \ + ((err) != nfserr_stale_stateid) && \ + ((err) != nfserr_bad_stateid)) + +extern time_t nfs4_laundromat(void); +extern int nfsd4_renew(clientid_t *clid); +extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, + stateid_t *stateid, int flags, struct file **filp); +extern int nfs4_share_conflict(struct svc_fh *current_fh, + unsigned int deny_type); +extern void nfs4_lock_state(void); +extern void nfs4_unlock_state(void); +extern int nfs4_in_grace(void); +extern int nfs4_check_open_reclaim(clientid_t *clid); +extern void put_nfs4_client(struct nfs4_client *clp); +extern void nfs4_free_stateowner(struct kref *kref); +extern void nfsd4_probe_callback(struct nfs4_client *clp); +extern void nfsd4_cb_recall(struct nfs4_delegation *dp); +extern void nfs4_put_delegation(struct nfs4_delegation *dp); + +static inline void +nfs4_put_stateowner(struct nfs4_stateowner *so) +{ + kref_put(&so->so_ref, nfs4_free_stateowner); +} + +static inline void +nfs4_get_stateowner(struct nfs4_stateowner *so) +{ + kref_get(&so->so_ref); +} + +#endif /* NFSD4_STATE_H */ diff --git a/include/linux/nfsd/stats.h b/include/linux/nfsd/stats.h new file mode 100644 index 000000000000..b6f1e0cda4f2 --- /dev/null +++ b/include/linux/nfsd/stats.h @@ -0,0 +1,44 @@ +/* + * linux/include/nfsd/stats.h + * + * Statistics for NFS server. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef LINUX_NFSD_STATS_H +#define LINUX_NFSD_STATS_H + +struct nfsd_stats { + unsigned int rchits; /* repcache hits */ + unsigned int rcmisses; /* repcache hits */ + unsigned int rcnocache; /* uncached reqs */ + unsigned int fh_stale; /* FH stale error */ + unsigned int fh_lookup; /* dentry cached */ + unsigned int fh_anon; /* anon file dentry returned */ + unsigned int fh_nocache_dir; /* filehandle not found in dcache */ + unsigned int fh_nocache_nondir; /* filehandle not found in dcache */ + unsigned int io_read; /* bytes returned to read requests */ + unsigned int io_write; /* bytes passed in write requests */ + unsigned int th_cnt; /* number of available threads */ + unsigned int th_usage[10]; /* number of ticks during which n perdeciles + * of available threads were in use */ + unsigned int th_fullcnt; /* number of times last free thread was used */ + unsigned int ra_size; /* size of ra cache */ + unsigned int ra_depth[11]; /* number of times ra entry was found that deep + * in the cache (10percentiles). [10] = not found */ +}; + +/* thread usage wraps very million seconds (approx one fortnight) */ +#define NFSD_USAGE_WRAP (HZ*1000000) + +#ifdef __KERNEL__ + +extern struct nfsd_stats nfsdstats; +extern struct svc_stat nfsd_svcstats; + +void nfsd_stat_init(void); +void nfsd_stat_shutdown(void); + +#endif /* __KERNEL__ */ +#endif /* LINUX_NFSD_STATS_H */ diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h new file mode 100644 index 000000000000..e65c9db6d13f --- /dev/null +++ b/include/linux/nfsd/syscall.h @@ -0,0 +1,125 @@ +/* + * include/linux/nfsd/syscall.h + * + * This file holds all declarations for the knfsd syscall interface. + * + * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef NFSD_SYSCALL_H +#define NFSD_SYSCALL_H + +#include <asm/types.h> +#ifdef __KERNEL__ +# include <linux/config.h> +# include <linux/types.h> +# include <linux/in.h> +#endif +#include <linux/posix_types.h> +#include <linux/nfsd/const.h> +#include <linux/nfsd/export.h> +#include <linux/nfsd/nfsfh.h> +#include <linux/nfsd/auth.h> + +/* + * Version of the syscall interface + */ +#define NFSCTL_VERSION 0x0201 + +/* + * These are the commands understood by nfsctl(). + */ +#define NFSCTL_SVC 0 /* This is a server process. */ +#define NFSCTL_ADDCLIENT 1 /* Add an NFS client. */ +#define NFSCTL_DELCLIENT 2 /* Remove an NFS client. */ +#define NFSCTL_EXPORT 3 /* export a file system. */ +#define NFSCTL_UNEXPORT 4 /* unexport a file system. */ +/*#define NFSCTL_UGIDUPDATE 5 / * update a client's uid/gid map. DISCARDED */ +/*#define NFSCTL_GETFH 6 / * get an fh by ino DISCARDED */ +#define NFSCTL_GETFD 7 /* get an fh by path (used by mountd) */ +#define NFSCTL_GETFS 8 /* get an fh by path with max FH len */ + +/* SVC */ +struct nfsctl_svc { + unsigned short svc_port; + int svc_nthreads; +}; + +/* ADDCLIENT/DELCLIENT */ +struct nfsctl_client { + char cl_ident[NFSCLNT_IDMAX+1]; + int cl_naddr; + struct in_addr cl_addrlist[NFSCLNT_ADDRMAX]; + int cl_fhkeytype; + int cl_fhkeylen; + unsigned char cl_fhkey[NFSCLNT_KEYMAX]; +}; + +/* EXPORT/UNEXPORT */ +struct nfsctl_export { + char ex_client[NFSCLNT_IDMAX+1]; + char ex_path[NFS_MAXPATHLEN+1]; + __kernel_old_dev_t ex_dev; + __kernel_ino_t ex_ino; + int ex_flags; + __kernel_uid_t ex_anon_uid; + __kernel_gid_t ex_anon_gid; +}; + +/* GETFD */ +struct nfsctl_fdparm { + struct sockaddr gd_addr; + char gd_path[NFS_MAXPATHLEN+1]; + int gd_version; +}; + +/* GETFS - GET Filehandle with Size */ +struct nfsctl_fsparm { + struct sockaddr gd_addr; + char gd_path[NFS_MAXPATHLEN+1]; + int gd_maxlen; +}; + +/* + * This is the argument union. + */ +struct nfsctl_arg { + int ca_version; /* safeguard */ + union { + struct nfsctl_svc u_svc; + struct nfsctl_client u_client; + struct nfsctl_export u_export; + struct nfsctl_fdparm u_getfd; + struct nfsctl_fsparm u_getfs; + /* + * The following dummy member is needed to preserve binary compatibility + * on platforms where alignof(void*)>alignof(int). It's needed because + * this union used to contain a member (u_umap) which contained a + * pointer. + */ + void *u_ptr; + } u; +#define ca_svc u.u_svc +#define ca_client u.u_client +#define ca_export u.u_export +#define ca_getfd u.u_getfd +#define ca_getfs u.u_getfs +}; + +union nfsctl_res { + __u8 cr_getfh[NFS_FHSIZE]; + struct knfsd_fh cr_getfs; +}; + +#ifdef __KERNEL__ +/* + * Kernel syscall implementation. + */ +extern int exp_addclient(struct nfsctl_client *ncp); +extern int exp_delclient(struct nfsctl_client *ncp); +extern int exp_export(struct nfsctl_export *nxp); +extern int exp_unexport(struct nfsctl_export *nxp); + +#endif /* __KERNEL__ */ + +#endif /* NFSD_SYSCALL_H */ diff --git a/include/linux/nfsd/xdr.h b/include/linux/nfsd/xdr.h new file mode 100644 index 000000000000..ecccef777dae --- /dev/null +++ b/include/linux/nfsd/xdr.h @@ -0,0 +1,172 @@ +/* + * linux/inxlude/linux/nfsd/xdr.h + * + * XDR types for nfsd. This is mainly a typing exercise. + */ + +#ifndef LINUX_NFSD_H +#define LINUX_NFSD_H + +#include <linux/fs.h> +#include <linux/vfs.h> +#include <linux/nfs.h> + +struct nfsd_fhandle { + struct svc_fh fh; +}; + +struct nfsd_sattrargs { + struct svc_fh fh; + struct iattr attrs; +}; + +struct nfsd_diropargs { + struct svc_fh fh; + char * name; + int len; +}; + +struct nfsd_readargs { + struct svc_fh fh; + __u32 offset; + __u32 count; + struct kvec vec[RPCSVC_MAXPAGES]; + int vlen; +}; + +struct nfsd_writeargs { + svc_fh fh; + __u32 offset; + int len; + struct kvec vec[RPCSVC_MAXPAGES]; + int vlen; +}; + +struct nfsd_createargs { + struct svc_fh fh; + char * name; + int len; + struct iattr attrs; +}; + +struct nfsd_renameargs { + struct svc_fh ffh; + char * fname; + int flen; + struct svc_fh tfh; + char * tname; + int tlen; +}; + +struct nfsd_readlinkargs { + struct svc_fh fh; + char * buffer; +}; + +struct nfsd_linkargs { + struct svc_fh ffh; + struct svc_fh tfh; + char * tname; + int tlen; +}; + +struct nfsd_symlinkargs { + struct svc_fh ffh; + char * fname; + int flen; + char * tname; + int tlen; + struct iattr attrs; +}; + +struct nfsd_readdirargs { + struct svc_fh fh; + __u32 cookie; + __u32 count; + u32 * buffer; +}; + +struct nfsd_attrstat { + struct svc_fh fh; +}; + +struct nfsd_diropres { + struct svc_fh fh; +}; + +struct nfsd_readlinkres { + int len; +}; + +struct nfsd_readres { + struct svc_fh fh; + unsigned long count; +}; + +struct nfsd_readdirres { + int count; + + struct readdir_cd common; + u32 * buffer; + int buflen; + u32 * offset; +}; + +struct nfsd_statfsres { + struct kstatfs stats; +}; + +/* + * Storage requirements for XDR arguments and results. + */ +union nfsd_xdrstore { + struct nfsd_sattrargs sattr; + struct nfsd_diropargs dirop; + struct nfsd_readargs read; + struct nfsd_writeargs write; + struct nfsd_createargs create; + struct nfsd_renameargs rename; + struct nfsd_linkargs link; + struct nfsd_symlinkargs symlink; + struct nfsd_readdirargs readdir; +}; + +#define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore) + + +int nfssvc_decode_void(struct svc_rqst *, u32 *, void *); +int nfssvc_decode_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *); +int nfssvc_decode_sattrargs(struct svc_rqst *, u32 *, + struct nfsd_sattrargs *); +int nfssvc_decode_diropargs(struct svc_rqst *, u32 *, + struct nfsd_diropargs *); +int nfssvc_decode_readargs(struct svc_rqst *, u32 *, + struct nfsd_readargs *); +int nfssvc_decode_writeargs(struct svc_rqst *, u32 *, + struct nfsd_writeargs *); +int nfssvc_decode_createargs(struct svc_rqst *, u32 *, + struct nfsd_createargs *); +int nfssvc_decode_renameargs(struct svc_rqst *, u32 *, + struct nfsd_renameargs *); +int nfssvc_decode_readlinkargs(struct svc_rqst *, u32 *, + struct nfsd_readlinkargs *); +int nfssvc_decode_linkargs(struct svc_rqst *, u32 *, + struct nfsd_linkargs *); +int nfssvc_decode_symlinkargs(struct svc_rqst *, u32 *, + struct nfsd_symlinkargs *); +int nfssvc_decode_readdirargs(struct svc_rqst *, u32 *, + struct nfsd_readdirargs *); +int nfssvc_encode_void(struct svc_rqst *, u32 *, void *); +int nfssvc_encode_attrstat(struct svc_rqst *, u32 *, struct nfsd_attrstat *); +int nfssvc_encode_diropres(struct svc_rqst *, u32 *, struct nfsd_diropres *); +int nfssvc_encode_readlinkres(struct svc_rqst *, u32 *, struct nfsd_readlinkres *); +int nfssvc_encode_readres(struct svc_rqst *, u32 *, struct nfsd_readres *); +int nfssvc_encode_statfsres(struct svc_rqst *, u32 *, struct nfsd_statfsres *); +int nfssvc_encode_readdirres(struct svc_rqst *, u32 *, struct nfsd_readdirres *); + +int nfssvc_encode_entry(struct readdir_cd *, const char *name, + int namlen, loff_t offset, ino_t ino, unsigned int); + +int nfssvc_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *); + +#endif /* LINUX_NFSD_H */ diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h new file mode 100644 index 000000000000..0ae9e0ef5f68 --- /dev/null +++ b/include/linux/nfsd/xdr3.h @@ -0,0 +1,321 @@ +/* + * linux/include/linux/nfsd/xdr3.h + * + * XDR types for NFSv3 in nfsd. + * + * Copyright (C) 1996-1998, Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef _LINUX_NFSD_XDR3_H +#define _LINUX_NFSD_XDR3_H + +#include <linux/nfsd/xdr.h> + +struct nfsd3_sattrargs { + struct svc_fh fh; + struct iattr attrs; + int check_guard; + time_t guardtime; +}; + +struct nfsd3_diropargs { + struct svc_fh fh; + char * name; + int len; +}; + +struct nfsd3_accessargs { + struct svc_fh fh; + unsigned int access; +}; + +struct nfsd3_readargs { + struct svc_fh fh; + __u64 offset; + __u32 count; + struct kvec vec[RPCSVC_MAXPAGES]; + int vlen; +}; + +struct nfsd3_writeargs { + svc_fh fh; + __u64 offset; + __u32 count; + int stable; + int len; + struct kvec vec[RPCSVC_MAXPAGES]; + int vlen; +}; + +struct nfsd3_createargs { + struct svc_fh fh; + char * name; + int len; + int createmode; + struct iattr attrs; + __u32 * verf; +}; + +struct nfsd3_mknodargs { + struct svc_fh fh; + char * name; + int len; + __u32 ftype; + __u32 major, minor; + struct iattr attrs; +}; + +struct nfsd3_renameargs { + struct svc_fh ffh; + char * fname; + int flen; + struct svc_fh tfh; + char * tname; + int tlen; +}; + +struct nfsd3_readlinkargs { + struct svc_fh fh; + char * buffer; +}; + +struct nfsd3_linkargs { + struct svc_fh ffh; + struct svc_fh tfh; + char * tname; + int tlen; +}; + +struct nfsd3_symlinkargs { + struct svc_fh ffh; + char * fname; + int flen; + char * tname; + int tlen; + struct iattr attrs; +}; + +struct nfsd3_readdirargs { + struct svc_fh fh; + __u64 cookie; + __u32 dircount; + __u32 count; + __u32 * verf; + u32 * buffer; +}; + +struct nfsd3_commitargs { + struct svc_fh fh; + __u64 offset; + __u32 count; +}; + +struct nfsd3_attrstat { + __u32 status; + struct svc_fh fh; +}; + +/* LOOKUP, CREATE, MKDIR, SYMLINK, MKNOD */ +struct nfsd3_diropres { + __u32 status; + struct svc_fh dirfh; + struct svc_fh fh; +}; + +struct nfsd3_accessres { + __u32 status; + struct svc_fh fh; + __u32 access; +}; + +struct nfsd3_readlinkres { + __u32 status; + struct svc_fh fh; + __u32 len; +}; + +struct nfsd3_readres { + __u32 status; + struct svc_fh fh; + unsigned long count; + int eof; +}; + +struct nfsd3_writeres { + __u32 status; + struct svc_fh fh; + unsigned long count; + int committed; +}; + +struct nfsd3_renameres { + __u32 status; + struct svc_fh ffh; + struct svc_fh tfh; +}; + +struct nfsd3_linkres { + __u32 status; + struct svc_fh tfh; + struct svc_fh fh; +}; + +struct nfsd3_readdirres { + __u32 status; + struct svc_fh fh; + int count; + __u32 verf[2]; + + struct readdir_cd common; + u32 * buffer; + int buflen; + u32 * offset; + u32 * offset1; + struct svc_rqst * rqstp; + +}; + +struct nfsd3_fsstatres { + __u32 status; + struct kstatfs stats; + __u32 invarsec; +}; + +struct nfsd3_fsinfores { + __u32 status; + __u32 f_rtmax; + __u32 f_rtpref; + __u32 f_rtmult; + __u32 f_wtmax; + __u32 f_wtpref; + __u32 f_wtmult; + __u32 f_dtpref; + __u64 f_maxfilesize; + __u32 f_properties; +}; + +struct nfsd3_pathconfres { + __u32 status; + __u32 p_link_max; + __u32 p_name_max; + __u32 p_no_trunc; + __u32 p_chown_restricted; + __u32 p_case_insensitive; + __u32 p_case_preserving; +}; + +struct nfsd3_commitres { + __u32 status; + struct svc_fh fh; +}; + +/* dummy type for release */ +struct nfsd3_fhandle_pair { + __u32 dummy; + struct svc_fh fh1; + struct svc_fh fh2; +}; + +/* + * Storage requirements for XDR arguments and results. + */ +union nfsd3_xdrstore { + struct nfsd3_sattrargs sattrargs; + struct nfsd3_diropargs diropargs; + struct nfsd3_readargs readargs; + struct nfsd3_writeargs writeargs; + struct nfsd3_createargs createargs; + struct nfsd3_renameargs renameargs; + struct nfsd3_linkargs linkargs; + struct nfsd3_symlinkargs symlinkargs; + struct nfsd3_readdirargs readdirargs; + struct nfsd3_diropres diropres; + struct nfsd3_accessres accessres; + struct nfsd3_readlinkres readlinkres; + struct nfsd3_readres readres; + struct nfsd3_writeres writeres; + struct nfsd3_renameres renameres; + struct nfsd3_linkres linkres; + struct nfsd3_readdirres readdirres; + struct nfsd3_fsstatres fsstatres; + struct nfsd3_fsinfores fsinfores; + struct nfsd3_pathconfres pathconfres; + struct nfsd3_commitres commitres; +}; + +#define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore) + +int nfs3svc_decode_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *); +int nfs3svc_decode_sattrargs(struct svc_rqst *, u32 *, + struct nfsd3_sattrargs *); +int nfs3svc_decode_diropargs(struct svc_rqst *, u32 *, + struct nfsd3_diropargs *); +int nfs3svc_decode_accessargs(struct svc_rqst *, u32 *, + struct nfsd3_accessargs *); +int nfs3svc_decode_readargs(struct svc_rqst *, u32 *, + struct nfsd3_readargs *); +int nfs3svc_decode_writeargs(struct svc_rqst *, u32 *, + struct nfsd3_writeargs *); +int nfs3svc_decode_createargs(struct svc_rqst *, u32 *, + struct nfsd3_createargs *); +int nfs3svc_decode_mkdirargs(struct svc_rqst *, u32 *, + struct nfsd3_createargs *); +int nfs3svc_decode_mknodargs(struct svc_rqst *, u32 *, + struct nfsd3_mknodargs *); +int nfs3svc_decode_renameargs(struct svc_rqst *, u32 *, + struct nfsd3_renameargs *); +int nfs3svc_decode_readlinkargs(struct svc_rqst *, u32 *, + struct nfsd3_readlinkargs *); +int nfs3svc_decode_linkargs(struct svc_rqst *, u32 *, + struct nfsd3_linkargs *); +int nfs3svc_decode_symlinkargs(struct svc_rqst *, u32 *, + struct nfsd3_symlinkargs *); +int nfs3svc_decode_readdirargs(struct svc_rqst *, u32 *, + struct nfsd3_readdirargs *); +int nfs3svc_decode_readdirplusargs(struct svc_rqst *, u32 *, + struct nfsd3_readdirargs *); +int nfs3svc_decode_commitargs(struct svc_rqst *, u32 *, + struct nfsd3_commitargs *); +int nfs3svc_encode_voidres(struct svc_rqst *, u32 *, void *); +int nfs3svc_encode_attrstat(struct svc_rqst *, u32 *, + struct nfsd3_attrstat *); +int nfs3svc_encode_wccstat(struct svc_rqst *, u32 *, + struct nfsd3_attrstat *); +int nfs3svc_encode_diropres(struct svc_rqst *, u32 *, + struct nfsd3_diropres *); +int nfs3svc_encode_accessres(struct svc_rqst *, u32 *, + struct nfsd3_accessres *); +int nfs3svc_encode_readlinkres(struct svc_rqst *, u32 *, + struct nfsd3_readlinkres *); +int nfs3svc_encode_readres(struct svc_rqst *, u32 *, struct nfsd3_readres *); +int nfs3svc_encode_writeres(struct svc_rqst *, u32 *, struct nfsd3_writeres *); +int nfs3svc_encode_createres(struct svc_rqst *, u32 *, + struct nfsd3_diropres *); +int nfs3svc_encode_renameres(struct svc_rqst *, u32 *, + struct nfsd3_renameres *); +int nfs3svc_encode_linkres(struct svc_rqst *, u32 *, + struct nfsd3_linkres *); +int nfs3svc_encode_readdirres(struct svc_rqst *, u32 *, + struct nfsd3_readdirres *); +int nfs3svc_encode_fsstatres(struct svc_rqst *, u32 *, + struct nfsd3_fsstatres *); +int nfs3svc_encode_fsinfores(struct svc_rqst *, u32 *, + struct nfsd3_fsinfores *); +int nfs3svc_encode_pathconfres(struct svc_rqst *, u32 *, + struct nfsd3_pathconfres *); +int nfs3svc_encode_commitres(struct svc_rqst *, u32 *, + struct nfsd3_commitres *); + +int nfs3svc_release_fhandle(struct svc_rqst *, u32 *, + struct nfsd3_attrstat *); +int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *, + struct nfsd3_fhandle_pair *); +int nfs3svc_encode_entry(struct readdir_cd *, const char *name, + int namlen, loff_t offset, ino_t ino, + unsigned int); +int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name, + int namlen, loff_t offset, ino_t ino, + unsigned int); + + +#endif /* _LINUX_NFSD_XDR3_H */ diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h new file mode 100644 index 000000000000..a1f5ad0be1bf --- /dev/null +++ b/include/linux/nfsd/xdr4.h @@ -0,0 +1,463 @@ +/* + * include/linux/nfsd/xdr4.h + * + * Server-side types for NFSv4. + * + * Copyright (c) 2002 The Regents of the University of Michigan. + * All rights reserved. + * + * Kendrick Smith <kmsmith@umich.edu> + * Andy Adamson <andros@umich.edu> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _LINUX_NFSD_XDR4_H +#define _LINUX_NFSD_XDR4_H + +#include <linux/nfs4.h> + +#define NFSD4_MAX_TAGLEN 128 +#define XDR_LEN(n) (((n) + 3) & ~3) + +struct nfsd4_change_info { + u32 atomic; + u32 before_ctime_sec; + u32 before_ctime_nsec; + u32 after_ctime_sec; + u32 after_ctime_nsec; +}; + +struct nfsd4_access { + u32 ac_req_access; /* request */ + u32 ac_supported; /* response */ + u32 ac_resp_access; /* response */ +}; + +struct nfsd4_close { + u32 cl_seqid; /* request */ + stateid_t cl_stateid; /* request+response */ + struct nfs4_stateowner * cl_stateowner; /* response */ +}; + +struct nfsd4_commit { + u64 co_offset; /* request */ + u32 co_count; /* request */ + nfs4_verifier co_verf; /* response */ +}; + +struct nfsd4_create { + u32 cr_namelen; /* request */ + char * cr_name; /* request */ + u32 cr_type; /* request */ + union { /* request */ + struct { + u32 namelen; + char *name; + } link; /* NF4LNK */ + struct { + u32 specdata1; + u32 specdata2; + } dev; /* NF4BLK, NF4CHR */ + } u; + u32 cr_bmval[2]; /* request */ + struct iattr cr_iattr; /* request */ + struct nfsd4_change_info cr_cinfo; /* response */ + struct nfs4_acl *cr_acl; +}; +#define cr_linklen u.link.namelen +#define cr_linkname u.link.name +#define cr_specdata1 u.dev.specdata1 +#define cr_specdata2 u.dev.specdata2 + +struct nfsd4_delegreturn { + stateid_t dr_stateid; +}; + +struct nfsd4_getattr { + u32 ga_bmval[2]; /* request */ + struct svc_fh *ga_fhp; /* response */ +}; + +struct nfsd4_link { + u32 li_namelen; /* request */ + char * li_name; /* request */ + struct nfsd4_change_info li_cinfo; /* response */ +}; + +struct nfsd4_lock_denied { + clientid_t ld_clientid; + struct nfs4_stateowner *ld_sop; + u64 ld_start; + u64 ld_length; + u32 ld_type; +}; + +struct nfsd4_lock { + /* request */ + u32 lk_type; + u32 lk_reclaim; /* boolean */ + u64 lk_offset; + u64 lk_length; + u32 lk_is_new; + union { + struct { + u32 open_seqid; + stateid_t open_stateid; + u32 lock_seqid; + clientid_t clientid; + struct xdr_netobj owner; + } new; + struct { + stateid_t lock_stateid; + u32 lock_seqid; + } old; + } v; + + /* response */ + union { + struct { + stateid_t stateid; + } ok; + struct nfsd4_lock_denied denied; + } u; + + struct nfs4_stateowner *lk_stateowner; +}; +#define lk_new_open_seqid v.new.open_seqid +#define lk_new_open_stateid v.new.open_stateid +#define lk_new_lock_seqid v.new.lock_seqid +#define lk_new_clientid v.new.clientid +#define lk_new_owner v.new.owner +#define lk_old_lock_stateid v.old.lock_stateid +#define lk_old_lock_seqid v.old.lock_seqid + +#define lk_rflags u.ok.rflags +#define lk_resp_stateid u.ok.stateid +#define lk_denied u.denied + + +struct nfsd4_lockt { + u32 lt_type; + clientid_t lt_clientid; + struct xdr_netobj lt_owner; + u64 lt_offset; + u64 lt_length; + struct nfs4_stateowner * lt_stateowner; + struct nfsd4_lock_denied lt_denied; +}; + + +struct nfsd4_locku { + u32 lu_type; + u32 lu_seqid; + stateid_t lu_stateid; + u64 lu_offset; + u64 lu_length; + struct nfs4_stateowner *lu_stateowner; +}; + + +struct nfsd4_lookup { + u32 lo_len; /* request */ + char * lo_name; /* request */ +}; + +struct nfsd4_putfh { + u32 pf_fhlen; /* request */ + char *pf_fhval; /* request */ +}; + +struct nfsd4_open { + u32 op_claim_type; /* request */ + struct xdr_netobj op_fname; /* request - everything but CLAIM_PREV */ + u32 op_delegate_type; /* request - CLAIM_PREV only */ + stateid_t op_delegate_stateid; /* request - response */ + u32 op_create; /* request */ + u32 op_createmode; /* request */ + u32 op_bmval[2]; /* request */ + union { /* request */ + struct iattr iattr; /* UNCHECKED4,GUARDED4 */ + nfs4_verifier verf; /* EXCLUSIVE4 */ + } u; + clientid_t op_clientid; /* request */ + struct xdr_netobj op_owner; /* request */ + u32 op_seqid; /* request */ + u32 op_share_access; /* request */ + u32 op_share_deny; /* request */ + stateid_t op_stateid; /* response */ + 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 */ + struct nfs4_acl *op_acl; +}; +#define op_iattr u.iattr +#define op_verf u.verf + +struct nfsd4_open_confirm { + stateid_t oc_req_stateid /* request */; + u32 oc_seqid /* request */; + stateid_t oc_resp_stateid /* response */; + struct nfs4_stateowner * oc_stateowner; /* response */ +}; + +struct nfsd4_open_downgrade { + stateid_t od_stateid; + u32 od_seqid; + u32 od_share_access; + u32 od_share_deny; + struct nfs4_stateowner *od_stateowner; +}; + + +struct nfsd4_read { + stateid_t rd_stateid; /* request */ + u64 rd_offset; /* request */ + u32 rd_length; /* request */ + struct kvec rd_iov[RPCSVC_MAXPAGES]; + int rd_vlen; + struct file *rd_filp; + + struct svc_rqst *rd_rqstp; /* response */ + struct svc_fh * rd_fhp; /* response */ +}; + +struct nfsd4_readdir { + u64 rd_cookie; /* request */ + nfs4_verifier rd_verf; /* request */ + u32 rd_dircount; /* request */ + u32 rd_maxcount; /* request */ + u32 rd_bmval[2]; /* request */ + struct svc_rqst *rd_rqstp; /* response */ + struct svc_fh * rd_fhp; /* response */ + + struct readdir_cd common; + u32 * buffer; + int buflen; + u32 * offset; +}; + +struct nfsd4_release_lockowner { + clientid_t rl_clientid; + struct xdr_netobj rl_owner; +}; +struct nfsd4_readlink { + struct svc_rqst *rl_rqstp; /* request */ + struct svc_fh * rl_fhp; /* request */ +}; + +struct nfsd4_remove { + u32 rm_namelen; /* request */ + char * rm_name; /* request */ + struct nfsd4_change_info rm_cinfo; /* response */ +}; + +struct nfsd4_rename { + u32 rn_snamelen; /* request */ + char * rn_sname; /* request */ + u32 rn_tnamelen; /* request */ + char * rn_tname; /* request */ + struct nfsd4_change_info rn_sinfo; /* response */ + struct nfsd4_change_info rn_tinfo; /* response */ +}; + +struct nfsd4_setattr { + stateid_t sa_stateid; /* request */ + u32 sa_bmval[2]; /* request */ + struct iattr sa_iattr; /* request */ + struct nfs4_acl *sa_acl; +}; + +struct nfsd4_setclientid { + nfs4_verifier se_verf; /* request */ + u32 se_namelen; /* request */ + char * se_name; /* request */ + u32 se_callback_prog; /* request */ + u32 se_callback_netid_len; /* request */ + char * se_callback_netid_val; /* request */ + u32 se_callback_addr_len; /* request */ + char * se_callback_addr_val; /* request */ + u32 se_callback_ident; /* request */ + clientid_t se_clientid; /* response */ + nfs4_verifier se_confirm; /* response */ +}; + +struct nfsd4_setclientid_confirm { + clientid_t sc_clientid; + nfs4_verifier sc_confirm; +}; + +/* also used for NVERIFY */ +struct nfsd4_verify { + u32 ve_bmval[2]; /* request */ + u32 ve_attrlen; /* request */ + char * ve_attrval; /* request */ +}; + +struct nfsd4_write { + stateid_t wr_stateid; /* request */ + u64 wr_offset; /* request */ + u32 wr_stable_how; /* request */ + u32 wr_buflen; /* request */ + struct kvec wr_vec[RPCSVC_MAXPAGES]; /* request */ + int wr_vlen; + + u32 wr_bytes_written; /* response */ + u32 wr_how_written; /* response */ + nfs4_verifier wr_verifier; /* response */ +}; + +struct nfsd4_op { + int opnum; + int status; + union { + struct nfsd4_access access; + struct nfsd4_close close; + struct nfsd4_commit commit; + struct nfsd4_create create; + struct nfsd4_delegreturn delegreturn; + struct nfsd4_getattr getattr; + struct svc_fh * getfh; + struct nfsd4_link link; + struct nfsd4_lock lock; + struct nfsd4_lockt lockt; + struct nfsd4_locku locku; + struct nfsd4_lookup lookup; + struct nfsd4_verify nverify; + struct nfsd4_open open; + struct nfsd4_open_confirm open_confirm; + struct nfsd4_open_downgrade open_downgrade; + struct nfsd4_putfh putfh; + struct nfsd4_read read; + struct nfsd4_readdir readdir; + struct nfsd4_readlink readlink; + struct nfsd4_remove remove; + struct nfsd4_rename rename; + clientid_t renew; + struct nfsd4_setattr setattr; + struct nfsd4_setclientid setclientid; + struct nfsd4_setclientid_confirm setclientid_confirm; + struct nfsd4_verify verify; + struct nfsd4_write write; + struct nfsd4_release_lockowner release_lockowner; + } u; + struct nfs4_replay * replay; +}; + +struct nfsd4_compoundargs { + /* scratch variables for XDR decode */ + u32 * p; + u32 * end; + struct page ** pagelist; + int pagelen; + u32 tmp[8]; + u32 * tmpp; + struct tmpbuf { + struct tmpbuf *next; + void (*release)(const void *); + void *buf; + } *to_free; + + struct svc_rqst *rqstp; + + u32 taglen; + char * tag; + u32 minorversion; + u32 opcnt; + struct nfsd4_op *ops; + struct nfsd4_op iops[8]; +}; + +struct nfsd4_compoundres { + /* scratch variables for XDR encode */ + u32 * p; + u32 * end; + struct xdr_buf * xbuf; + struct svc_rqst * rqstp; + + u32 taglen; + char * tag; + u32 opcnt; + u32 * tagp; /* where to encode tag and opcount */ +}; + +#define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) + +static inline void +set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) +{ + BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved); + cinfo->atomic = 1; + cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; + cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; + cinfo->after_ctime_sec = fhp->fh_post_ctime.tv_sec; + cinfo->after_ctime_nsec = fhp->fh_post_ctime.tv_nsec; +} + +int nfs4svc_encode_voidres(struct svc_rqst *, u32 *, void *); +int nfs4svc_decode_compoundargs(struct svc_rqst *, u32 *, + struct nfsd4_compoundargs *); +int nfs4svc_encode_compoundres(struct svc_rqst *, u32 *, + struct nfsd4_compoundres *); +void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *); +void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op); +int nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, + struct dentry *dentry, u32 *buffer, int *countp, + u32 *bmval, struct svc_rqst *); +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); +extern int nfsd4_open_confirm(struct svc_rqst *rqstp, + struct svc_fh *current_fh, struct nfsd4_open_confirm *oc); +extern int nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, + struct nfsd4_close *close); +extern int nfsd4_open_downgrade(struct svc_rqst *rqstp, + struct svc_fh *current_fh, struct nfsd4_open_downgrade *od); +extern int nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, + struct nfsd4_lock *lock); +extern int nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, + struct nfsd4_lockt *lockt); +extern int nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, + struct nfsd4_locku *locku); +extern int +nfsd4_release_lockowner(struct svc_rqst *rqstp, + struct nfsd4_release_lockowner *rlockowner); +extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *); +extern int nfsd4_delegreturn(struct svc_rqst *rqstp, + struct svc_fh *current_fh, struct nfsd4_delegreturn *dr); +#endif + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ |