9cf514ccfa
Add support for the GETDEVICEINFO, LAYOUTGET, LAYOUTCOMMIT and LAYOUTRETURN NFSv4.1 operations, as well as backing code to manage outstanding layouts and devices. Layout management is very straight forward, with a nfs4_layout_stateid structure that extends nfs4_stid to manage layout stateids as the top-level structure. It is linked into the nfs4_file and nfs4_client structures like the other stateids, and contains a linked list of layouts that hang of the stateid. The actual layout operations are implemented in layout drivers that are not part of this commit, but will be added later. The worst part of this commit is the management of the pNFS device IDs, which suffers from a specification that is not sanely implementable due to the fact that the device-IDs are global and not bound to an export, and have a small enough size so that we can't store the fsid portion of a file handle, and must never be reused. As we still do need perform all export authentication and validation checks on a device ID passed to GETDEVICEINFO we are caught between a rock and a hard place. To work around this issue we add a new hash that maps from a 64-bit integer to a fsid so that we can look up the export to authenticate against it, a 32-bit integer as a generation that we can bump when changing the device, and a currently unused 32-bit integer that could be used in the future to handle more than a single device per export. Entries in this hash table are never deleted as we can't reuse the ids anyway, and would have a severe lifetime problem anyway as Linux export structures are temporary structures that can go away under load. Parts of the XDR data, structures and marshaling/unmarshaling code, as well as many concepts are derived from the old pNFS server implementation from Andy Adamson, Benny Halevy, Dean Hildebrand, Marc Eshel, Fred Isaman, Mike Sager, Ricardo Labiaga and many others. Signed-off-by: Christoph Hellwig <hch@lst.de>
113 lines
2.9 KiB
C
113 lines
2.9 KiB
C
/*
|
|
* Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
|
|
*/
|
|
#ifndef NFSD_EXPORT_H
|
|
#define NFSD_EXPORT_H
|
|
|
|
#include <linux/sunrpc/cache.h>
|
|
#include <uapi/linux/nfsd/export.h>
|
|
|
|
struct knfsd_fh;
|
|
struct svc_fh;
|
|
struct svc_rqst;
|
|
|
|
/*
|
|
* FS Locations
|
|
*/
|
|
|
|
#define MAX_FS_LOCATIONS 128
|
|
|
|
struct nfsd4_fs_location {
|
|
char *hosts; /* colon separated list of hosts */
|
|
char *path; /* slash separated list of path components */
|
|
};
|
|
|
|
struct nfsd4_fs_locations {
|
|
uint32_t locations_count;
|
|
struct nfsd4_fs_location *locations;
|
|
/* If we're not actually serving this data ourselves (only providing a
|
|
* list of replicas that do serve it) then we set "migrated": */
|
|
int migrated;
|
|
};
|
|
|
|
/*
|
|
* We keep an array of pseudoflavors with the export, in order from most
|
|
* to least preferred. For the foreseeable future, we don't expect more
|
|
* than the eight pseudoflavors null, unix, krb5, krb5i, krb5p, skpm3,
|
|
* spkm3i, and spkm3p (and using all 8 at once should be rare).
|
|
*/
|
|
#define MAX_SECINFO_LIST 8
|
|
#define EX_UUID_LEN 16
|
|
|
|
struct exp_flavor_info {
|
|
u32 pseudoflavor;
|
|
u32 flags;
|
|
};
|
|
|
|
struct svc_export {
|
|
struct cache_head h;
|
|
struct auth_domain * ex_client;
|
|
int ex_flags;
|
|
struct path ex_path;
|
|
kuid_t ex_anon_uid;
|
|
kgid_t ex_anon_gid;
|
|
int ex_fsid;
|
|
unsigned char * ex_uuid; /* 16 byte fsid */
|
|
struct nfsd4_fs_locations ex_fslocs;
|
|
uint32_t ex_nflavors;
|
|
struct exp_flavor_info ex_flavors[MAX_SECINFO_LIST];
|
|
enum pnfs_layouttype ex_layout_type;
|
|
struct nfsd4_deviceid_map *ex_devid_map;
|
|
struct cache_detail *cd;
|
|
};
|
|
|
|
/* an "export key" (expkey) maps a filehandlefragement to an
|
|
* svc_export for a given client. There can be several per export,
|
|
* for the different fsid types.
|
|
*/
|
|
struct svc_expkey {
|
|
struct cache_head h;
|
|
|
|
struct auth_domain * ek_client;
|
|
int ek_fsidtype;
|
|
u32 ek_fsid[6];
|
|
|
|
struct path ek_path;
|
|
};
|
|
|
|
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
|
|
#define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE)
|
|
#define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
|
|
|
|
int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp);
|
|
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
|
|
|
|
/*
|
|
* Function declarations
|
|
*/
|
|
int nfsd_export_init(struct net *);
|
|
void nfsd_export_shutdown(struct net *);
|
|
void nfsd_export_flush(struct net *);
|
|
struct svc_export * rqst_exp_get_by_name(struct svc_rqst *,
|
|
struct path *);
|
|
struct svc_export * rqst_exp_parent(struct svc_rqst *,
|
|
struct path *);
|
|
struct svc_export * rqst_find_fsidzero_export(struct svc_rqst *);
|
|
int exp_rootfh(struct net *, struct auth_domain *,
|
|
char *path, struct knfsd_fh *, int maxsize);
|
|
__be32 exp_pseudoroot(struct svc_rqst *, struct svc_fh *);
|
|
__be32 nfserrno(int errno);
|
|
|
|
static inline void exp_put(struct svc_export *exp)
|
|
{
|
|
cache_put(&exp->h, exp->cd);
|
|
}
|
|
|
|
static inline struct svc_export *exp_get(struct svc_export *exp)
|
|
{
|
|
cache_get(&exp->h);
|
|
return exp;
|
|
}
|
|
struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *);
|
|
|
|
#endif /* NFSD_EXPORT_H */
|