| .. | .. |
|---|
| 17 | 17 | #include <linux/nfs3.h> |
|---|
| 18 | 18 | #include <linux/nfs4.h> |
|---|
| 19 | 19 | #include <linux/sunrpc/svc.h> |
|---|
| 20 | +#include <linux/sunrpc/svc_xprt.h> |
|---|
| 20 | 21 | #include <linux/sunrpc/msg_prot.h> |
|---|
| 22 | +#include <linux/sunrpc/addr.h> |
|---|
| 21 | 23 | |
|---|
| 22 | 24 | #include <uapi/linux/nfsd/debug.h> |
|---|
| 23 | 25 | |
|---|
| 26 | +#include "netns.h" |
|---|
| 24 | 27 | #include "stats.h" |
|---|
| 25 | 28 | #include "export.h" |
|---|
| 26 | 29 | |
|---|
| .. | .. |
|---|
| 73 | 76 | /* |
|---|
| 74 | 77 | * Function prototypes. |
|---|
| 75 | 78 | */ |
|---|
| 76 | | -int nfsd_svc(int nrservs, struct net *net); |
|---|
| 79 | +int nfsd_svc(int nrservs, struct net *net, const struct cred *cred); |
|---|
| 77 | 80 | int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); |
|---|
| 78 | 81 | |
|---|
| 79 | 82 | int nfsd_nrthreads(struct net *); |
|---|
| .. | .. |
|---|
| 84 | 87 | int nfsd_pool_stats_release(struct inode *, struct file *); |
|---|
| 85 | 88 | |
|---|
| 86 | 89 | void nfsd_destroy(struct net *net); |
|---|
| 90 | + |
|---|
| 91 | +bool i_am_nfsd(void); |
|---|
| 92 | + |
|---|
| 93 | +int get_nfsdfs(struct net *); |
|---|
| 94 | + |
|---|
| 95 | +struct nfsdfs_client { |
|---|
| 96 | + struct kref cl_ref; |
|---|
| 97 | + void (*cl_release)(struct kref *kref); |
|---|
| 98 | +}; |
|---|
| 99 | + |
|---|
| 100 | +struct nfsdfs_client *get_nfsdfs_client(struct inode *); |
|---|
| 101 | +struct dentry *nfsd_client_mkdir(struct nfsd_net *nn, |
|---|
| 102 | + struct nfsdfs_client *ncl, u32 id, const struct tree_descr *); |
|---|
| 103 | +void nfsd_client_rmdir(struct dentry *dentry); |
|---|
| 104 | + |
|---|
| 87 | 105 | |
|---|
| 88 | 106 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) |
|---|
| 89 | 107 | #ifdef CONFIG_NFSD_V2_ACL |
|---|
| .. | .. |
|---|
| 98 | 116 | #endif |
|---|
| 99 | 117 | #endif |
|---|
| 100 | 118 | |
|---|
| 119 | +struct nfsd_net; |
|---|
| 120 | + |
|---|
| 101 | 121 | enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; |
|---|
| 102 | | -int nfsd_vers(int vers, enum vers_op change); |
|---|
| 103 | | -int nfsd_minorversion(u32 minorversion, enum vers_op change); |
|---|
| 104 | | -void nfsd_reset_versions(void); |
|---|
| 122 | +int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change); |
|---|
| 123 | +int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change); |
|---|
| 124 | +void nfsd_reset_versions(struct nfsd_net *nn); |
|---|
| 105 | 125 | int nfsd_create_serv(struct net *net); |
|---|
| 106 | 126 | |
|---|
| 107 | 127 | extern int nfsd_max_blksize; |
|---|
| .. | .. |
|---|
| 109 | 129 | static inline int nfsd_v4client(struct svc_rqst *rq) |
|---|
| 110 | 130 | { |
|---|
| 111 | 131 | return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4; |
|---|
| 132 | +} |
|---|
| 133 | +static inline struct user_namespace * |
|---|
| 134 | +nfsd_user_namespace(const struct svc_rqst *rqstp) |
|---|
| 135 | +{ |
|---|
| 136 | + const struct cred *cred = rqstp->rq_xprt->xpt_cred; |
|---|
| 137 | + return cred ? cred->user_ns : &init_user_ns; |
|---|
| 112 | 138 | } |
|---|
| 113 | 139 | |
|---|
| 114 | 140 | /* |
|---|
| .. | .. |
|---|
| 122 | 148 | int nfs4_state_start_net(struct net *net); |
|---|
| 123 | 149 | void nfs4_state_shutdown(void); |
|---|
| 124 | 150 | void nfs4_state_shutdown_net(struct net *net); |
|---|
| 125 | | -void nfs4_reset_lease(time_t leasetime); |
|---|
| 126 | 151 | int nfs4_reset_recoverydir(char *recdir); |
|---|
| 127 | 152 | char * nfs4_recoverydir(void); |
|---|
| 128 | 153 | bool nfsd4_spo_must_allow(struct svc_rqst *rqstp); |
|---|
| .. | .. |
|---|
| 133 | 158 | static inline int nfs4_state_start_net(struct net *net) { return 0; } |
|---|
| 134 | 159 | static inline void nfs4_state_shutdown(void) { } |
|---|
| 135 | 160 | static inline void nfs4_state_shutdown_net(struct net *net) { } |
|---|
| 136 | | -static inline void nfs4_reset_lease(time_t leasetime) { } |
|---|
| 137 | 161 | static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } |
|---|
| 138 | 162 | static inline char * nfs4_recoverydir(void) {return NULL; } |
|---|
| 139 | 163 | static inline bool nfsd4_spo_must_allow(struct svc_rqst *rqstp) |
|---|
| .. | .. |
|---|
| 260 | 284 | #define nfserr_union_notsupp cpu_to_be32(NFS4ERR_UNION_NOTSUPP) |
|---|
| 261 | 285 | #define nfserr_offload_denied cpu_to_be32(NFS4ERR_OFFLOAD_DENIED) |
|---|
| 262 | 286 | #define nfserr_wrong_lfs cpu_to_be32(NFS4ERR_WRONG_LFS) |
|---|
| 263 | | -#define nfserr_badlabel cpu_to_be32(NFS4ERR_BADLABEL) |
|---|
| 287 | +#define nfserr_badlabel cpu_to_be32(NFS4ERR_BADLABEL) |
|---|
| 288 | +#define nfserr_file_open cpu_to_be32(NFS4ERR_FILE_OPEN) |
|---|
| 289 | +#define nfserr_xattr2big cpu_to_be32(NFS4ERR_XATTR2BIG) |
|---|
| 290 | +#define nfserr_noxattr cpu_to_be32(NFS4ERR_NOXATTR) |
|---|
| 264 | 291 | |
|---|
| 265 | 292 | /* error codes for internal use */ |
|---|
| 266 | 293 | /* if a request fails due to kmalloc failure, it gets dropped. |
|---|
| .. | .. |
|---|
| 362 | 389 | (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \ |
|---|
| 363 | 390 | FATTR4_WORD2_CHANGE_ATTR_TYPE | \ |
|---|
| 364 | 391 | FATTR4_WORD2_MODE_UMASK | \ |
|---|
| 365 | | - NFSD4_2_SECURITY_ATTRS) |
|---|
| 392 | + NFSD4_2_SECURITY_ATTRS | \ |
|---|
| 393 | + FATTR4_WORD2_XATTR_SUPPORT) |
|---|
| 366 | 394 | |
|---|
| 367 | 395 | extern const u32 nfsd_suppattrs[3][3]; |
|---|
| 368 | 396 | |
|---|
| 397 | +static inline __be32 nfsd4_set_netaddr(struct sockaddr *addr, |
|---|
| 398 | + struct nfs42_netaddr *netaddr) |
|---|
| 399 | +{ |
|---|
| 400 | + struct sockaddr_in *sin = (struct sockaddr_in *)addr; |
|---|
| 401 | + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; |
|---|
| 402 | + unsigned int port; |
|---|
| 403 | + size_t ret_addr, ret_port; |
|---|
| 404 | + |
|---|
| 405 | + switch (addr->sa_family) { |
|---|
| 406 | + case AF_INET: |
|---|
| 407 | + port = ntohs(sin->sin_port); |
|---|
| 408 | + sprintf(netaddr->netid, "tcp"); |
|---|
| 409 | + netaddr->netid_len = 3; |
|---|
| 410 | + break; |
|---|
| 411 | + case AF_INET6: |
|---|
| 412 | + port = ntohs(sin6->sin6_port); |
|---|
| 413 | + sprintf(netaddr->netid, "tcp6"); |
|---|
| 414 | + netaddr->netid_len = 4; |
|---|
| 415 | + break; |
|---|
| 416 | + default: |
|---|
| 417 | + return nfserr_inval; |
|---|
| 418 | + } |
|---|
| 419 | + ret_addr = rpc_ntop(addr, netaddr->addr, sizeof(netaddr->addr)); |
|---|
| 420 | + ret_port = snprintf(netaddr->addr + ret_addr, |
|---|
| 421 | + RPCBIND_MAXUADDRLEN + 1 - ret_addr, |
|---|
| 422 | + ".%u.%u", port >> 8, port & 0xff); |
|---|
| 423 | + WARN_ON(ret_port >= RPCBIND_MAXUADDRLEN + 1 - ret_addr); |
|---|
| 424 | + netaddr->addr_len = ret_addr + ret_port; |
|---|
| 425 | + return 0; |
|---|
| 426 | +} |
|---|
| 427 | + |
|---|
| 369 | 428 | static inline bool bmval_is_subset(const u32 *bm1, const u32 *bm2) |
|---|
| 370 | 429 | { |
|---|
| 371 | 430 | return !((bm1[0] & ~bm2[0]) || |
|---|