162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * NFS internal definitions 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "nfs4_fs.h" 762306a36Sopenharmony_ci#include <linux/fs_context.h> 862306a36Sopenharmony_ci#include <linux/security.h> 962306a36Sopenharmony_ci#include <linux/crc32.h> 1062306a36Sopenharmony_ci#include <linux/sunrpc/addr.h> 1162306a36Sopenharmony_ci#include <linux/nfs_page.h> 1262306a36Sopenharmony_ci#include <linux/wait_bit.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define NFS_SB_MASK (SB_RDONLY|SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS) 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciextern const struct export_operations nfs_export_ops; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistruct nfs_string; 1962306a36Sopenharmony_cistruct nfs_pageio_descriptor; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic inline void nfs_attr_check_mountpoint(struct super_block *parent, struct nfs_fattr *fattr) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci if (!nfs_fsid_equal(&NFS_SB(parent)->fsid, &fattr->fsid)) 2462306a36Sopenharmony_ci fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci if (((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) == 0) || 3062306a36Sopenharmony_ci (((fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) && 3162306a36Sopenharmony_ci ((fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) == 0))) 3262306a36Sopenharmony_ci return 0; 3362306a36Sopenharmony_ci return 1; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic inline bool nfs_lookup_is_soft_revalidate(const struct dentry *dentry) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci if (!(NFS_SB(dentry->d_sb)->flags & NFS_MOUNT_SOFTREVAL)) 3962306a36Sopenharmony_ci return false; 4062306a36Sopenharmony_ci if (!d_is_positive(dentry) || !NFS_FH(d_inode(dentry))->size) 4162306a36Sopenharmony_ci return false; 4262306a36Sopenharmony_ci return true; 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic inline fmode_t flags_to_mode(int flags) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci fmode_t res = (__force fmode_t)flags & FMODE_EXEC; 4862306a36Sopenharmony_ci if ((flags & O_ACCMODE) != O_WRONLY) 4962306a36Sopenharmony_ci res |= FMODE_READ; 5062306a36Sopenharmony_ci if ((flags & O_ACCMODE) != O_RDONLY) 5162306a36Sopenharmony_ci res |= FMODE_WRITE; 5262306a36Sopenharmony_ci return res; 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* 5662306a36Sopenharmony_ci * Note: RFC 1813 doesn't limit the number of auth flavors that 5762306a36Sopenharmony_ci * a server can return, so make something up. 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ci#define NFS_MAX_SECFLAVORS (12) 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* 6262306a36Sopenharmony_ci * Value used if the user did not specify a port value. 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_ci#define NFS_UNSPEC_PORT (-1) 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define NFS_UNSPEC_RETRANS (UINT_MAX) 6762306a36Sopenharmony_ci#define NFS_UNSPEC_TIMEO (UINT_MAX) 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistruct nfs_client_initdata { 7062306a36Sopenharmony_ci unsigned long init_flags; 7162306a36Sopenharmony_ci const char *hostname; /* Hostname of the server */ 7262306a36Sopenharmony_ci const struct sockaddr_storage *addr; /* Address of the server */ 7362306a36Sopenharmony_ci const char *nodename; /* Hostname of the client */ 7462306a36Sopenharmony_ci const char *ip_addr; /* IP address of the client */ 7562306a36Sopenharmony_ci size_t addrlen; 7662306a36Sopenharmony_ci struct nfs_subversion *nfs_mod; 7762306a36Sopenharmony_ci int proto; 7862306a36Sopenharmony_ci u32 minorversion; 7962306a36Sopenharmony_ci unsigned int nconnect; 8062306a36Sopenharmony_ci unsigned int max_connect; 8162306a36Sopenharmony_ci struct net *net; 8262306a36Sopenharmony_ci const struct rpc_timeout *timeparms; 8362306a36Sopenharmony_ci const struct cred *cred; 8462306a36Sopenharmony_ci struct xprtsec_parms xprtsec; 8562306a36Sopenharmony_ci unsigned long connect_timeout; 8662306a36Sopenharmony_ci unsigned long reconnect_timeout; 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* 9062306a36Sopenharmony_ci * In-kernel mount arguments 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_cistruct nfs_fs_context { 9362306a36Sopenharmony_ci bool internal; 9462306a36Sopenharmony_ci bool skip_reconfig_option_check; 9562306a36Sopenharmony_ci bool need_mount; 9662306a36Sopenharmony_ci bool sloppy; 9762306a36Sopenharmony_ci unsigned int flags; /* NFS{,4}_MOUNT_* flags */ 9862306a36Sopenharmony_ci unsigned int rsize, wsize; 9962306a36Sopenharmony_ci unsigned int timeo, retrans; 10062306a36Sopenharmony_ci unsigned int acregmin, acregmax; 10162306a36Sopenharmony_ci unsigned int acdirmin, acdirmax; 10262306a36Sopenharmony_ci unsigned int namlen; 10362306a36Sopenharmony_ci unsigned int options; 10462306a36Sopenharmony_ci unsigned int bsize; 10562306a36Sopenharmony_ci struct nfs_auth_info auth_info; 10662306a36Sopenharmony_ci rpc_authflavor_t selected_flavor; 10762306a36Sopenharmony_ci struct xprtsec_parms xprtsec; 10862306a36Sopenharmony_ci char *client_address; 10962306a36Sopenharmony_ci unsigned int version; 11062306a36Sopenharmony_ci unsigned int minorversion; 11162306a36Sopenharmony_ci char *fscache_uniq; 11262306a36Sopenharmony_ci unsigned short protofamily; 11362306a36Sopenharmony_ci unsigned short mountfamily; 11462306a36Sopenharmony_ci bool has_sec_mnt_opts; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci struct { 11762306a36Sopenharmony_ci union { 11862306a36Sopenharmony_ci struct sockaddr address; 11962306a36Sopenharmony_ci struct sockaddr_storage _address; 12062306a36Sopenharmony_ci }; 12162306a36Sopenharmony_ci size_t addrlen; 12262306a36Sopenharmony_ci char *hostname; 12362306a36Sopenharmony_ci u32 version; 12462306a36Sopenharmony_ci int port; 12562306a36Sopenharmony_ci unsigned short protocol; 12662306a36Sopenharmony_ci } mount_server; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci struct { 12962306a36Sopenharmony_ci union { 13062306a36Sopenharmony_ci struct sockaddr address; 13162306a36Sopenharmony_ci struct sockaddr_storage _address; 13262306a36Sopenharmony_ci }; 13362306a36Sopenharmony_ci size_t addrlen; 13462306a36Sopenharmony_ci char *hostname; 13562306a36Sopenharmony_ci char *export_path; 13662306a36Sopenharmony_ci int port; 13762306a36Sopenharmony_ci unsigned short protocol; 13862306a36Sopenharmony_ci unsigned short nconnect; 13962306a36Sopenharmony_ci unsigned short max_connect; 14062306a36Sopenharmony_ci unsigned short export_path_len; 14162306a36Sopenharmony_ci } nfs_server; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci struct nfs_fh *mntfh; 14462306a36Sopenharmony_ci struct nfs_server *server; 14562306a36Sopenharmony_ci struct nfs_subversion *nfs_mod; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci /* Information for a cloned mount. */ 14862306a36Sopenharmony_ci struct nfs_clone_mount { 14962306a36Sopenharmony_ci struct super_block *sb; 15062306a36Sopenharmony_ci struct dentry *dentry; 15162306a36Sopenharmony_ci struct nfs_fattr *fattr; 15262306a36Sopenharmony_ci unsigned int inherited_bsize; 15362306a36Sopenharmony_ci } clone_data; 15462306a36Sopenharmony_ci}; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci#define nfs_errorf(fc, fmt, ...) ((fc)->log.log ? \ 15762306a36Sopenharmony_ci errorf(fc, fmt, ## __VA_ARGS__) : \ 15862306a36Sopenharmony_ci ({ dprintk(fmt "\n", ## __VA_ARGS__); })) 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci#define nfs_ferrorf(fc, fac, fmt, ...) ((fc)->log.log ? \ 16162306a36Sopenharmony_ci errorf(fc, fmt, ## __VA_ARGS__) : \ 16262306a36Sopenharmony_ci ({ dfprintk(fac, fmt "\n", ## __VA_ARGS__); })) 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#define nfs_invalf(fc, fmt, ...) ((fc)->log.log ? \ 16562306a36Sopenharmony_ci invalf(fc, fmt, ## __VA_ARGS__) : \ 16662306a36Sopenharmony_ci ({ dprintk(fmt "\n", ## __VA_ARGS__); -EINVAL; })) 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#define nfs_finvalf(fc, fac, fmt, ...) ((fc)->log.log ? \ 16962306a36Sopenharmony_ci invalf(fc, fmt, ## __VA_ARGS__) : \ 17062306a36Sopenharmony_ci ({ dfprintk(fac, fmt "\n", ## __VA_ARGS__); -EINVAL; })) 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci#define nfs_warnf(fc, fmt, ...) ((fc)->log.log ? \ 17362306a36Sopenharmony_ci warnf(fc, fmt, ## __VA_ARGS__) : \ 17462306a36Sopenharmony_ci ({ dprintk(fmt "\n", ## __VA_ARGS__); })) 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci#define nfs_fwarnf(fc, fac, fmt, ...) ((fc)->log.log ? \ 17762306a36Sopenharmony_ci warnf(fc, fmt, ## __VA_ARGS__) : \ 17862306a36Sopenharmony_ci ({ dfprintk(fac, fmt "\n", ## __VA_ARGS__); })) 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic inline struct nfs_fs_context *nfs_fc2context(const struct fs_context *fc) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci return fc->fs_private; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/* mount_clnt.c */ 18662306a36Sopenharmony_cistruct nfs_mount_request { 18762306a36Sopenharmony_ci struct sockaddr_storage *sap; 18862306a36Sopenharmony_ci size_t salen; 18962306a36Sopenharmony_ci char *hostname; 19062306a36Sopenharmony_ci char *dirpath; 19162306a36Sopenharmony_ci u32 version; 19262306a36Sopenharmony_ci unsigned short protocol; 19362306a36Sopenharmony_ci struct nfs_fh *fh; 19462306a36Sopenharmony_ci int noresvport; 19562306a36Sopenharmony_ci unsigned int *auth_flav_len; 19662306a36Sopenharmony_ci rpc_authflavor_t *auth_flavs; 19762306a36Sopenharmony_ci struct net *net; 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ciextern int nfs_mount(struct nfs_mount_request *info, int timeo, int retrans); 20162306a36Sopenharmony_ciextern void nfs_umount(const struct nfs_mount_request *info); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci/* client.c */ 20462306a36Sopenharmony_ciextern const struct rpc_program nfs_program; 20562306a36Sopenharmony_ciextern void nfs_clients_init(struct net *net); 20662306a36Sopenharmony_ciextern void nfs_clients_exit(struct net *net); 20762306a36Sopenharmony_ciextern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *); 20862306a36Sopenharmony_ciint nfs_create_rpc_client(struct nfs_client *, const struct nfs_client_initdata *, rpc_authflavor_t); 20962306a36Sopenharmony_cistruct nfs_client *nfs_get_client(const struct nfs_client_initdata *); 21062306a36Sopenharmony_ciint nfs_probe_server(struct nfs_server *, struct nfs_fh *); 21162306a36Sopenharmony_civoid nfs_server_insert_lists(struct nfs_server *); 21262306a36Sopenharmony_civoid nfs_server_remove_lists(struct nfs_server *); 21362306a36Sopenharmony_civoid nfs_init_timeout_values(struct rpc_timeout *to, int proto, int timeo, int retrans); 21462306a36Sopenharmony_ciint nfs_init_server_rpcclient(struct nfs_server *, const struct rpc_timeout *t, 21562306a36Sopenharmony_ci rpc_authflavor_t); 21662306a36Sopenharmony_cistruct nfs_server *nfs_alloc_server(void); 21762306a36Sopenharmony_civoid nfs_server_copy_userdata(struct nfs_server *, struct nfs_server *); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ciextern void nfs_put_client(struct nfs_client *); 22062306a36Sopenharmony_ciextern void nfs_free_client(struct nfs_client *); 22162306a36Sopenharmony_ciextern struct nfs_client *nfs4_find_client_ident(struct net *, int); 22262306a36Sopenharmony_ciextern struct nfs_client * 22362306a36Sopenharmony_cinfs4_find_client_sessionid(struct net *, const struct sockaddr *, 22462306a36Sopenharmony_ci struct nfs4_sessionid *, u32); 22562306a36Sopenharmony_ciextern struct nfs_server *nfs_create_server(struct fs_context *); 22662306a36Sopenharmony_ciextern void nfs4_server_set_init_caps(struct nfs_server *); 22762306a36Sopenharmony_ciextern struct nfs_server *nfs4_create_server(struct fs_context *); 22862306a36Sopenharmony_ciextern struct nfs_server *nfs4_create_referral_server(struct fs_context *); 22962306a36Sopenharmony_ciextern int nfs4_update_server(struct nfs_server *server, const char *hostname, 23062306a36Sopenharmony_ci struct sockaddr_storage *sap, size_t salen, 23162306a36Sopenharmony_ci struct net *net); 23262306a36Sopenharmony_ciextern void nfs_free_server(struct nfs_server *server); 23362306a36Sopenharmony_ciextern struct nfs_server *nfs_clone_server(struct nfs_server *, 23462306a36Sopenharmony_ci struct nfs_fh *, 23562306a36Sopenharmony_ci struct nfs_fattr *, 23662306a36Sopenharmony_ci rpc_authflavor_t); 23762306a36Sopenharmony_ciextern bool nfs_client_init_is_complete(const struct nfs_client *clp); 23862306a36Sopenharmony_ciextern int nfs_client_init_status(const struct nfs_client *clp); 23962306a36Sopenharmony_ciextern int nfs_wait_client_init_complete(const struct nfs_client *clp); 24062306a36Sopenharmony_ciextern void nfs_mark_client_ready(struct nfs_client *clp, int state); 24162306a36Sopenharmony_ciextern struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv, 24262306a36Sopenharmony_ci const struct sockaddr_storage *ds_addr, 24362306a36Sopenharmony_ci int ds_addrlen, int ds_proto, 24462306a36Sopenharmony_ci unsigned int ds_timeo, 24562306a36Sopenharmony_ci unsigned int ds_retrans, 24662306a36Sopenharmony_ci u32 minor_version); 24762306a36Sopenharmony_ciextern struct rpc_clnt *nfs4_find_or_create_ds_client(struct nfs_client *, 24862306a36Sopenharmony_ci struct inode *); 24962306a36Sopenharmony_ciextern struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv, 25062306a36Sopenharmony_ci const struct sockaddr_storage *ds_addr, int ds_addrlen, 25162306a36Sopenharmony_ci int ds_proto, unsigned int ds_timeo, 25262306a36Sopenharmony_ci unsigned int ds_retrans); 25362306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS 25462306a36Sopenharmony_ciextern int __init nfs_fs_proc_init(void); 25562306a36Sopenharmony_ciextern void nfs_fs_proc_exit(void); 25662306a36Sopenharmony_ciextern int nfs_fs_proc_net_init(struct net *net); 25762306a36Sopenharmony_ciextern void nfs_fs_proc_net_exit(struct net *net); 25862306a36Sopenharmony_ci#else 25962306a36Sopenharmony_cistatic inline int nfs_fs_proc_net_init(struct net *net) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci return 0; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_cistatic inline void nfs_fs_proc_net_exit(struct net *net) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_cistatic inline int nfs_fs_proc_init(void) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci return 0; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_cistatic inline void nfs_fs_proc_exit(void) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci#endif 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/* callback_xdr.c */ 27662306a36Sopenharmony_ciextern const struct svc_version nfs4_callback_version1; 27762306a36Sopenharmony_ciextern const struct svc_version nfs4_callback_version4; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci/* fs_context.c */ 28062306a36Sopenharmony_ciextern struct file_system_type nfs_fs_type; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/* pagelist.c */ 28362306a36Sopenharmony_ciextern int __init nfs_init_nfspagecache(void); 28462306a36Sopenharmony_ciextern void nfs_destroy_nfspagecache(void); 28562306a36Sopenharmony_ciextern int __init nfs_init_readpagecache(void); 28662306a36Sopenharmony_ciextern void nfs_destroy_readpagecache(void); 28762306a36Sopenharmony_ciextern int __init nfs_init_writepagecache(void); 28862306a36Sopenharmony_ciextern void nfs_destroy_writepagecache(void); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ciextern int __init nfs_init_directcache(void); 29162306a36Sopenharmony_ciextern void nfs_destroy_directcache(void); 29262306a36Sopenharmony_ciextern void nfs_pgheader_init(struct nfs_pageio_descriptor *desc, 29362306a36Sopenharmony_ci struct nfs_pgio_header *hdr, 29462306a36Sopenharmony_ci void (*release)(struct nfs_pgio_header *hdr)); 29562306a36Sopenharmony_civoid nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos); 29662306a36Sopenharmony_ciint nfs_iocounter_wait(struct nfs_lock_context *l_ctx); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ciextern const struct nfs_pageio_ops nfs_pgio_rw_ops; 29962306a36Sopenharmony_cistruct nfs_pgio_header *nfs_pgio_header_alloc(const struct nfs_rw_ops *); 30062306a36Sopenharmony_civoid nfs_pgio_header_free(struct nfs_pgio_header *); 30162306a36Sopenharmony_ciint nfs_generic_pgio(struct nfs_pageio_descriptor *, struct nfs_pgio_header *); 30262306a36Sopenharmony_ciint nfs_initiate_pgio(struct rpc_clnt *clnt, struct nfs_pgio_header *hdr, 30362306a36Sopenharmony_ci const struct cred *cred, const struct nfs_rpc_ops *rpc_ops, 30462306a36Sopenharmony_ci const struct rpc_call_ops *call_ops, int how, int flags); 30562306a36Sopenharmony_civoid nfs_free_request(struct nfs_page *req); 30662306a36Sopenharmony_cistruct nfs_pgio_mirror * 30762306a36Sopenharmony_cinfs_pgio_current_mirror(struct nfs_pageio_descriptor *desc); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic inline bool nfs_match_open_context(const struct nfs_open_context *ctx1, 31062306a36Sopenharmony_ci const struct nfs_open_context *ctx2) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci return cred_fscmp(ctx1->cred, ctx2->cred) == 0 && ctx1->state == ctx2->state; 31362306a36Sopenharmony_ci} 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci/* nfs2xdr.c */ 31662306a36Sopenharmony_ciextern const struct rpc_procinfo nfs_procedures[]; 31762306a36Sopenharmony_ciextern int nfs2_decode_dirent(struct xdr_stream *, 31862306a36Sopenharmony_ci struct nfs_entry *, bool); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci/* nfs3xdr.c */ 32162306a36Sopenharmony_ciextern const struct rpc_procinfo nfs3_procedures[]; 32262306a36Sopenharmony_ciextern int nfs3_decode_dirent(struct xdr_stream *, 32362306a36Sopenharmony_ci struct nfs_entry *, bool); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci/* nfs4xdr.c */ 32662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_NFS_V4) 32762306a36Sopenharmony_ciextern int nfs4_decode_dirent(struct xdr_stream *, 32862306a36Sopenharmony_ci struct nfs_entry *, bool); 32962306a36Sopenharmony_ci#endif 33062306a36Sopenharmony_ci#ifdef CONFIG_NFS_V4_1 33162306a36Sopenharmony_ciextern const u32 nfs41_maxread_overhead; 33262306a36Sopenharmony_ciextern const u32 nfs41_maxwrite_overhead; 33362306a36Sopenharmony_ciextern const u32 nfs41_maxgetdevinfo_overhead; 33462306a36Sopenharmony_ci#endif 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci/* nfs4proc.c */ 33762306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_NFS_V4) 33862306a36Sopenharmony_ciextern const struct rpc_procinfo nfs4_procedures[]; 33962306a36Sopenharmony_ci#endif 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci#ifdef CONFIG_NFS_V4_SECURITY_LABEL 34262306a36Sopenharmony_ciextern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags); 34362306a36Sopenharmony_cistatic inline struct nfs4_label * 34462306a36Sopenharmony_cinfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci if (!dst || !src) 34762306a36Sopenharmony_ci return NULL; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (src->len > NFS4_MAXLABELLEN) 35062306a36Sopenharmony_ci return NULL; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci dst->lfs = src->lfs; 35362306a36Sopenharmony_ci dst->pi = src->pi; 35462306a36Sopenharmony_ci dst->len = src->len; 35562306a36Sopenharmony_ci memcpy(dst->label, src->label, src->len); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci return dst; 35862306a36Sopenharmony_ci} 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci if (nfs_server_capable(&nfsi->vfs_inode, NFS_CAP_SECURITY_LABEL)) 36362306a36Sopenharmony_ci nfsi->cache_validity |= NFS_INO_INVALID_LABEL; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci#else 36662306a36Sopenharmony_cistatic inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; } 36762306a36Sopenharmony_cistatic inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_cistatic inline struct nfs4_label * 37162306a36Sopenharmony_cinfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci return NULL; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_SECURITY_LABEL */ 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci/* proc.c */ 37862306a36Sopenharmony_civoid nfs_close_context(struct nfs_open_context *ctx, int is_sync); 37962306a36Sopenharmony_ciextern struct nfs_client *nfs_init_client(struct nfs_client *clp, 38062306a36Sopenharmony_ci const struct nfs_client_initdata *); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci/* dir.c */ 38362306a36Sopenharmony_ciextern void nfs_readdir_record_entry_cache_hit(struct inode *dir); 38462306a36Sopenharmony_ciextern void nfs_readdir_record_entry_cache_miss(struct inode *dir); 38562306a36Sopenharmony_ciextern unsigned long nfs_access_cache_count(struct shrinker *shrink, 38662306a36Sopenharmony_ci struct shrink_control *sc); 38762306a36Sopenharmony_ciextern unsigned long nfs_access_cache_scan(struct shrinker *shrink, 38862306a36Sopenharmony_ci struct shrink_control *sc); 38962306a36Sopenharmony_cistruct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int); 39062306a36Sopenharmony_civoid nfs_d_prune_case_insensitive_aliases(struct inode *inode); 39162306a36Sopenharmony_ciint nfs_create(struct mnt_idmap *, struct inode *, struct dentry *, 39262306a36Sopenharmony_ci umode_t, bool); 39362306a36Sopenharmony_ciint nfs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *, 39462306a36Sopenharmony_ci umode_t); 39562306a36Sopenharmony_ciint nfs_rmdir(struct inode *, struct dentry *); 39662306a36Sopenharmony_ciint nfs_unlink(struct inode *, struct dentry *); 39762306a36Sopenharmony_ciint nfs_symlink(struct mnt_idmap *, struct inode *, struct dentry *, 39862306a36Sopenharmony_ci const char *); 39962306a36Sopenharmony_ciint nfs_link(struct dentry *, struct inode *, struct dentry *); 40062306a36Sopenharmony_ciint nfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *, umode_t, 40162306a36Sopenharmony_ci dev_t); 40262306a36Sopenharmony_ciint nfs_rename(struct mnt_idmap *, struct inode *, struct dentry *, 40362306a36Sopenharmony_ci struct inode *, struct dentry *, unsigned int); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci#ifdef CONFIG_NFS_V4_2 40662306a36Sopenharmony_cistatic inline __u32 nfs_access_xattr_mask(const struct nfs_server *server) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci if (!(server->caps & NFS_CAP_XATTR)) 40962306a36Sopenharmony_ci return 0; 41062306a36Sopenharmony_ci return NFS4_ACCESS_XAREAD | NFS4_ACCESS_XAWRITE | NFS4_ACCESS_XALIST; 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci#else 41362306a36Sopenharmony_cistatic inline __u32 nfs_access_xattr_mask(const struct nfs_server *server) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci return 0; 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci#endif 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci/* file.c */ 42062306a36Sopenharmony_ciint nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync); 42162306a36Sopenharmony_ciloff_t nfs_file_llseek(struct file *, loff_t, int); 42262306a36Sopenharmony_cissize_t nfs_file_read(struct kiocb *, struct iov_iter *); 42362306a36Sopenharmony_cissize_t nfs_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, 42462306a36Sopenharmony_ci size_t len, unsigned int flags); 42562306a36Sopenharmony_ciint nfs_file_mmap(struct file *, struct vm_area_struct *); 42662306a36Sopenharmony_cissize_t nfs_file_write(struct kiocb *, struct iov_iter *); 42762306a36Sopenharmony_ciint nfs_file_release(struct inode *, struct file *); 42862306a36Sopenharmony_ciint nfs_lock(struct file *, int, struct file_lock *); 42962306a36Sopenharmony_ciint nfs_flock(struct file *, int, struct file_lock *); 43062306a36Sopenharmony_ciint nfs_check_flags(int); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci/* inode.c */ 43362306a36Sopenharmony_ciextern struct workqueue_struct *nfsiod_workqueue; 43462306a36Sopenharmony_ciextern struct inode *nfs_alloc_inode(struct super_block *sb); 43562306a36Sopenharmony_ciextern void nfs_free_inode(struct inode *); 43662306a36Sopenharmony_ciextern int nfs_write_inode(struct inode *, struct writeback_control *); 43762306a36Sopenharmony_ciextern int nfs_drop_inode(struct inode *); 43862306a36Sopenharmony_ciextern void nfs_clear_inode(struct inode *); 43962306a36Sopenharmony_ciextern void nfs_evict_inode(struct inode *); 44062306a36Sopenharmony_ciextern void nfs_zap_acl_cache(struct inode *inode); 44162306a36Sopenharmony_ciextern void nfs_set_cache_invalid(struct inode *inode, unsigned long flags); 44262306a36Sopenharmony_ciextern bool nfs_check_cache_invalid(struct inode *, unsigned long); 44362306a36Sopenharmony_ciextern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci/* super.c */ 44662306a36Sopenharmony_ciextern const struct super_operations nfs_sops; 44762306a36Sopenharmony_cibool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t); 44862306a36Sopenharmony_ciint nfs_try_get_tree(struct fs_context *); 44962306a36Sopenharmony_ciint nfs_get_tree_common(struct fs_context *); 45062306a36Sopenharmony_civoid nfs_kill_super(struct super_block *); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ciextern struct rpc_stat nfs_rpcstat; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ciextern int __init register_nfs_fs(void); 45562306a36Sopenharmony_ciextern void __exit unregister_nfs_fs(void); 45662306a36Sopenharmony_ciextern bool nfs_sb_active(struct super_block *sb); 45762306a36Sopenharmony_ciextern void nfs_sb_deactive(struct super_block *sb); 45862306a36Sopenharmony_ciextern int nfs_client_for_each_server(struct nfs_client *clp, 45962306a36Sopenharmony_ci int (*fn)(struct nfs_server *, void *), 46062306a36Sopenharmony_ci void *data); 46162306a36Sopenharmony_ci#ifdef CONFIG_NFS_FSCACHE 46262306a36Sopenharmony_ciextern const struct netfs_request_ops nfs_netfs_ops; 46362306a36Sopenharmony_ci#endif 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci/* io.c */ 46662306a36Sopenharmony_ciextern void nfs_start_io_read(struct inode *inode); 46762306a36Sopenharmony_ciextern void nfs_end_io_read(struct inode *inode); 46862306a36Sopenharmony_ciextern void nfs_start_io_write(struct inode *inode); 46962306a36Sopenharmony_ciextern void nfs_end_io_write(struct inode *inode); 47062306a36Sopenharmony_ciextern void nfs_start_io_direct(struct inode *inode); 47162306a36Sopenharmony_ciextern void nfs_end_io_direct(struct inode *inode); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_cistatic inline bool nfs_file_io_is_buffered(struct nfs_inode *nfsi) 47462306a36Sopenharmony_ci{ 47562306a36Sopenharmony_ci return test_bit(NFS_INO_ODIRECT, &nfsi->flags) == 0; 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci/* namespace.c */ 47962306a36Sopenharmony_ci#define NFS_PATH_CANONICAL 1 48062306a36Sopenharmony_ciextern char *nfs_path(char **p, struct dentry *dentry, 48162306a36Sopenharmony_ci char *buffer, ssize_t buflen, unsigned flags); 48262306a36Sopenharmony_ciextern struct vfsmount *nfs_d_automount(struct path *path); 48362306a36Sopenharmony_ciint nfs_submount(struct fs_context *, struct nfs_server *); 48462306a36Sopenharmony_ciint nfs_do_submount(struct fs_context *); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci/* getroot.c */ 48762306a36Sopenharmony_ciextern int nfs_get_root(struct super_block *s, struct fs_context *fc); 48862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_NFS_V4) 48962306a36Sopenharmony_ciextern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool); 49062306a36Sopenharmony_ci#endif 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cistruct nfs_pgio_completion_ops; 49362306a36Sopenharmony_ci/* read.c */ 49462306a36Sopenharmony_ciextern const struct nfs_pgio_completion_ops nfs_async_read_completion_ops; 49562306a36Sopenharmony_ciextern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, 49662306a36Sopenharmony_ci struct inode *inode, bool force_mds, 49762306a36Sopenharmony_ci const struct nfs_pgio_completion_ops *compl_ops); 49862306a36Sopenharmony_ciextern bool nfs_read_alloc_scratch(struct nfs_pgio_header *hdr, size_t size); 49962306a36Sopenharmony_ciextern int nfs_read_add_folio(struct nfs_pageio_descriptor *pgio, 50062306a36Sopenharmony_ci struct nfs_open_context *ctx, 50162306a36Sopenharmony_ci struct folio *folio); 50262306a36Sopenharmony_ciextern void nfs_pageio_complete_read(struct nfs_pageio_descriptor *pgio); 50362306a36Sopenharmony_ciextern void nfs_read_prepare(struct rpc_task *task, void *calldata); 50462306a36Sopenharmony_ciextern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci/* super.c */ 50762306a36Sopenharmony_civoid nfs_umount_begin(struct super_block *); 50862306a36Sopenharmony_ciint nfs_statfs(struct dentry *, struct kstatfs *); 50962306a36Sopenharmony_ciint nfs_show_options(struct seq_file *, struct dentry *); 51062306a36Sopenharmony_ciint nfs_show_devname(struct seq_file *, struct dentry *); 51162306a36Sopenharmony_ciint nfs_show_path(struct seq_file *, struct dentry *); 51262306a36Sopenharmony_ciint nfs_show_stats(struct seq_file *, struct dentry *); 51362306a36Sopenharmony_ciint nfs_reconfigure(struct fs_context *); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci/* write.c */ 51662306a36Sopenharmony_ciextern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, 51762306a36Sopenharmony_ci struct inode *inode, int ioflags, bool force_mds, 51862306a36Sopenharmony_ci const struct nfs_pgio_completion_ops *compl_ops); 51962306a36Sopenharmony_ciextern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); 52062306a36Sopenharmony_ciextern void nfs_commit_free(struct nfs_commit_data *p); 52162306a36Sopenharmony_ciextern void nfs_commit_prepare(struct rpc_task *task, void *calldata); 52262306a36Sopenharmony_ciextern int nfs_initiate_commit(struct rpc_clnt *clnt, 52362306a36Sopenharmony_ci struct nfs_commit_data *data, 52462306a36Sopenharmony_ci const struct nfs_rpc_ops *nfs_ops, 52562306a36Sopenharmony_ci const struct rpc_call_ops *call_ops, 52662306a36Sopenharmony_ci int how, int flags); 52762306a36Sopenharmony_ciextern void nfs_init_commit(struct nfs_commit_data *data, 52862306a36Sopenharmony_ci struct list_head *head, 52962306a36Sopenharmony_ci struct pnfs_layout_segment *lseg, 53062306a36Sopenharmony_ci struct nfs_commit_info *cinfo); 53162306a36Sopenharmony_ciint nfs_scan_commit_list(struct list_head *src, struct list_head *dst, 53262306a36Sopenharmony_ci struct nfs_commit_info *cinfo, int max); 53362306a36Sopenharmony_ciunsigned long nfs_reqs_to_commit(struct nfs_commit_info *); 53462306a36Sopenharmony_ciint nfs_scan_commit(struct inode *inode, struct list_head *dst, 53562306a36Sopenharmony_ci struct nfs_commit_info *cinfo); 53662306a36Sopenharmony_civoid nfs_mark_request_commit(struct nfs_page *req, 53762306a36Sopenharmony_ci struct pnfs_layout_segment *lseg, 53862306a36Sopenharmony_ci struct nfs_commit_info *cinfo, 53962306a36Sopenharmony_ci u32 ds_commit_idx); 54062306a36Sopenharmony_ciint nfs_write_need_commit(struct nfs_pgio_header *); 54162306a36Sopenharmony_civoid nfs_writeback_update_inode(struct nfs_pgio_header *hdr); 54262306a36Sopenharmony_ciint nfs_generic_commit_list(struct inode *inode, struct list_head *head, 54362306a36Sopenharmony_ci int how, struct nfs_commit_info *cinfo); 54462306a36Sopenharmony_civoid nfs_retry_commit(struct list_head *page_list, 54562306a36Sopenharmony_ci struct pnfs_layout_segment *lseg, 54662306a36Sopenharmony_ci struct nfs_commit_info *cinfo, 54762306a36Sopenharmony_ci u32 ds_commit_idx); 54862306a36Sopenharmony_civoid nfs_commitdata_release(struct nfs_commit_data *data); 54962306a36Sopenharmony_civoid nfs_request_add_commit_list(struct nfs_page *req, 55062306a36Sopenharmony_ci struct nfs_commit_info *cinfo); 55162306a36Sopenharmony_civoid nfs_request_add_commit_list_locked(struct nfs_page *req, 55262306a36Sopenharmony_ci struct list_head *dst, 55362306a36Sopenharmony_ci struct nfs_commit_info *cinfo); 55462306a36Sopenharmony_civoid nfs_request_remove_commit_list(struct nfs_page *req, 55562306a36Sopenharmony_ci struct nfs_commit_info *cinfo); 55662306a36Sopenharmony_civoid nfs_init_cinfo(struct nfs_commit_info *cinfo, 55762306a36Sopenharmony_ci struct inode *inode, 55862306a36Sopenharmony_ci struct nfs_direct_req *dreq); 55962306a36Sopenharmony_ciint nfs_key_timeout_notify(struct file *filp, struct inode *inode); 56062306a36Sopenharmony_cibool nfs_ctx_key_to_expire(struct nfs_open_context *ctx, struct inode *inode); 56162306a36Sopenharmony_civoid nfs_pageio_stop_mirroring(struct nfs_pageio_descriptor *pgio); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ciint nfs_filemap_write_and_wait_range(struct address_space *mapping, 56462306a36Sopenharmony_ci loff_t lstart, loff_t lend); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci#ifdef CONFIG_NFS_V4_1 56762306a36Sopenharmony_cistatic inline void 56862306a36Sopenharmony_cipnfs_bucket_clear_pnfs_ds_commit_verifiers(struct pnfs_commit_bucket *buckets, 56962306a36Sopenharmony_ci unsigned int nbuckets) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci unsigned int i; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci for (i = 0; i < nbuckets; i++) 57462306a36Sopenharmony_ci buckets[i].direct_verf.committed = NFS_INVALID_STABLE_HOW; 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_cistatic inline 57762306a36Sopenharmony_civoid nfs_clear_pnfs_ds_commit_verifiers(struct pnfs_ds_commit_info *cinfo) 57862306a36Sopenharmony_ci{ 57962306a36Sopenharmony_ci struct pnfs_commit_array *array; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci rcu_read_lock(); 58262306a36Sopenharmony_ci list_for_each_entry_rcu(array, &cinfo->commits, cinfo_list) 58362306a36Sopenharmony_ci pnfs_bucket_clear_pnfs_ds_commit_verifiers(array->buckets, 58462306a36Sopenharmony_ci array->nbuckets); 58562306a36Sopenharmony_ci rcu_read_unlock(); 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci#else 58862306a36Sopenharmony_cistatic inline 58962306a36Sopenharmony_civoid nfs_clear_pnfs_ds_commit_verifiers(struct pnfs_ds_commit_info *cinfo) 59062306a36Sopenharmony_ci{ 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci#endif 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci#ifdef CONFIG_MIGRATION 59562306a36Sopenharmony_ciint nfs_migrate_folio(struct address_space *, struct folio *dst, 59662306a36Sopenharmony_ci struct folio *src, enum migrate_mode); 59762306a36Sopenharmony_ci#else 59862306a36Sopenharmony_ci#define nfs_migrate_folio NULL 59962306a36Sopenharmony_ci#endif 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_cistatic inline int 60262306a36Sopenharmony_cinfs_write_verifier_cmp(const struct nfs_write_verifier *v1, 60362306a36Sopenharmony_ci const struct nfs_write_verifier *v2) 60462306a36Sopenharmony_ci{ 60562306a36Sopenharmony_ci return memcmp(v1->data, v2->data, sizeof(v1->data)); 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_cistatic inline bool 60962306a36Sopenharmony_cinfs_write_match_verf(const struct nfs_writeverf *verf, 61062306a36Sopenharmony_ci struct nfs_page *req) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci return verf->committed > NFS_UNSTABLE && 61362306a36Sopenharmony_ci !nfs_write_verifier_cmp(&req->wb_verf, &verf->verifier); 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_cistatic inline gfp_t nfs_io_gfp_mask(void) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci if (current->flags & PF_WQ_WORKER) 61962306a36Sopenharmony_ci return GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN; 62062306a36Sopenharmony_ci return GFP_KERNEL; 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci/* 62462306a36Sopenharmony_ci * Special version of should_remove_suid() that ignores capabilities. 62562306a36Sopenharmony_ci */ 62662306a36Sopenharmony_cistatic inline int nfs_should_remove_suid(const struct inode *inode) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci umode_t mode = inode->i_mode; 62962306a36Sopenharmony_ci int kill = 0; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci /* suid always must be killed */ 63262306a36Sopenharmony_ci if (unlikely(mode & S_ISUID)) 63362306a36Sopenharmony_ci kill = ATTR_KILL_SUID; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci /* 63662306a36Sopenharmony_ci * sgid without any exec bits is just a mandatory locking mark; leave 63762306a36Sopenharmony_ci * it alone. If some exec bits are set, it's a real sgid; kill it. 63862306a36Sopenharmony_ci */ 63962306a36Sopenharmony_ci if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) 64062306a36Sopenharmony_ci kill |= ATTR_KILL_SGID; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci if (unlikely(kill && S_ISREG(mode))) 64362306a36Sopenharmony_ci return kill; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci return 0; 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci/* unlink.c */ 64962306a36Sopenharmony_ciextern struct rpc_task * 65062306a36Sopenharmony_cinfs_async_rename(struct inode *old_dir, struct inode *new_dir, 65162306a36Sopenharmony_ci struct dentry *old_dentry, struct dentry *new_dentry, 65262306a36Sopenharmony_ci void (*complete)(struct rpc_task *, struct nfs_renamedata *)); 65362306a36Sopenharmony_ciextern int nfs_sillyrename(struct inode *dir, struct dentry *dentry); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci/* direct.c */ 65662306a36Sopenharmony_civoid nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo, 65762306a36Sopenharmony_ci struct nfs_direct_req *dreq); 65862306a36Sopenharmony_ciextern ssize_t nfs_dreq_bytes_left(struct nfs_direct_req *dreq, loff_t offset); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci/* nfs4proc.c */ 66162306a36Sopenharmony_ciextern struct nfs_client *nfs4_init_client(struct nfs_client *clp, 66262306a36Sopenharmony_ci const struct nfs_client_initdata *); 66362306a36Sopenharmony_ciextern int nfs40_walk_client_list(struct nfs_client *clp, 66462306a36Sopenharmony_ci struct nfs_client **result, 66562306a36Sopenharmony_ci const struct cred *cred); 66662306a36Sopenharmony_ciextern int nfs41_walk_client_list(struct nfs_client *clp, 66762306a36Sopenharmony_ci struct nfs_client **result, 66862306a36Sopenharmony_ci const struct cred *cred); 66962306a36Sopenharmony_ciextern void nfs4_test_session_trunk(struct rpc_clnt *clnt, 67062306a36Sopenharmony_ci struct rpc_xprt *xprt, 67162306a36Sopenharmony_ci void *data); 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_cistatic inline struct inode *nfs_igrab_and_active(struct inode *inode) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci struct super_block *sb = inode->i_sb; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci if (sb && nfs_sb_active(sb)) { 67862306a36Sopenharmony_ci if (igrab(inode)) 67962306a36Sopenharmony_ci return inode; 68062306a36Sopenharmony_ci nfs_sb_deactive(sb); 68162306a36Sopenharmony_ci } 68262306a36Sopenharmony_ci return NULL; 68362306a36Sopenharmony_ci} 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_cistatic inline void nfs_iput_and_deactive(struct inode *inode) 68662306a36Sopenharmony_ci{ 68762306a36Sopenharmony_ci if (inode != NULL) { 68862306a36Sopenharmony_ci struct super_block *sb = inode->i_sb; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci iput(inode); 69162306a36Sopenharmony_ci nfs_sb_deactive(sb); 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci} 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci/* 69662306a36Sopenharmony_ci * Determine the device name as a string 69762306a36Sopenharmony_ci */ 69862306a36Sopenharmony_cistatic inline char *nfs_devname(struct dentry *dentry, 69962306a36Sopenharmony_ci char *buffer, ssize_t buflen) 70062306a36Sopenharmony_ci{ 70162306a36Sopenharmony_ci char *dummy; 70262306a36Sopenharmony_ci return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL); 70362306a36Sopenharmony_ci} 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci/* 70662306a36Sopenharmony_ci * Determine the actual block size (and log2 thereof) 70762306a36Sopenharmony_ci */ 70862306a36Sopenharmony_cistatic inline 70962306a36Sopenharmony_ciunsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp) 71062306a36Sopenharmony_ci{ 71162306a36Sopenharmony_ci /* make sure blocksize is a power of two */ 71262306a36Sopenharmony_ci if ((bsize & (bsize - 1)) || nrbitsp) { 71362306a36Sopenharmony_ci unsigned char nrbits; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--) 71662306a36Sopenharmony_ci ; 71762306a36Sopenharmony_ci bsize = 1 << nrbits; 71862306a36Sopenharmony_ci if (nrbitsp) 71962306a36Sopenharmony_ci *nrbitsp = nrbits; 72062306a36Sopenharmony_ci } 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci return bsize; 72362306a36Sopenharmony_ci} 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci/* 72662306a36Sopenharmony_ci * Calculate the number of 512byte blocks used. 72762306a36Sopenharmony_ci */ 72862306a36Sopenharmony_cistatic inline blkcnt_t nfs_calc_block_size(u64 tsize) 72962306a36Sopenharmony_ci{ 73062306a36Sopenharmony_ci blkcnt_t used = (tsize + 511) >> 9; 73162306a36Sopenharmony_ci return (used > ULONG_MAX) ? ULONG_MAX : used; 73262306a36Sopenharmony_ci} 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci/* 73562306a36Sopenharmony_ci * Compute and set NFS server blocksize 73662306a36Sopenharmony_ci */ 73762306a36Sopenharmony_cistatic inline 73862306a36Sopenharmony_ciunsigned long nfs_block_size(unsigned long bsize, unsigned char *nrbitsp) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci if (bsize < NFS_MIN_FILE_IO_SIZE) 74162306a36Sopenharmony_ci bsize = NFS_DEF_FILE_IO_SIZE; 74262306a36Sopenharmony_ci else if (bsize >= NFS_MAX_FILE_IO_SIZE) 74362306a36Sopenharmony_ci bsize = NFS_MAX_FILE_IO_SIZE; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci return nfs_block_bits(bsize, nrbitsp); 74662306a36Sopenharmony_ci} 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci/* 74962306a36Sopenharmony_ci * Compute and set NFS server rsize / wsize 75062306a36Sopenharmony_ci */ 75162306a36Sopenharmony_cistatic inline 75262306a36Sopenharmony_ciunsigned long nfs_io_size(unsigned long iosize, enum xprt_transports proto) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci if (iosize < NFS_MIN_FILE_IO_SIZE) 75562306a36Sopenharmony_ci iosize = NFS_DEF_FILE_IO_SIZE; 75662306a36Sopenharmony_ci else if (iosize >= NFS_MAX_FILE_IO_SIZE) 75762306a36Sopenharmony_ci iosize = NFS_MAX_FILE_IO_SIZE; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci if (proto == XPRT_TRANSPORT_UDP || iosize < PAGE_SIZE) 76062306a36Sopenharmony_ci return nfs_block_bits(iosize, NULL); 76162306a36Sopenharmony_ci return iosize & PAGE_MASK; 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci/* 76562306a36Sopenharmony_ci * Determine the maximum file size for a superblock 76662306a36Sopenharmony_ci */ 76762306a36Sopenharmony_cistatic inline 76862306a36Sopenharmony_civoid nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) 76962306a36Sopenharmony_ci{ 77062306a36Sopenharmony_ci sb->s_maxbytes = (loff_t)maxfilesize; 77162306a36Sopenharmony_ci if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0) 77262306a36Sopenharmony_ci sb->s_maxbytes = MAX_LFS_FILESIZE; 77362306a36Sopenharmony_ci} 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci/* 77662306a36Sopenharmony_ci * Record the page as unstable (an extra writeback period) and mark its 77762306a36Sopenharmony_ci * inode as dirty. 77862306a36Sopenharmony_ci */ 77962306a36Sopenharmony_cistatic inline void nfs_folio_mark_unstable(struct folio *folio, 78062306a36Sopenharmony_ci struct nfs_commit_info *cinfo) 78162306a36Sopenharmony_ci{ 78262306a36Sopenharmony_ci if (folio && !cinfo->dreq) { 78362306a36Sopenharmony_ci struct inode *inode = folio_file_mapping(folio)->host; 78462306a36Sopenharmony_ci long nr = folio_nr_pages(folio); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci /* This page is really still in write-back - just that the 78762306a36Sopenharmony_ci * writeback is happening on the server now. 78862306a36Sopenharmony_ci */ 78962306a36Sopenharmony_ci node_stat_mod_folio(folio, NR_WRITEBACK, nr); 79062306a36Sopenharmony_ci wb_stat_mod(&inode_to_bdi(inode)->wb, WB_WRITEBACK, nr); 79162306a36Sopenharmony_ci __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci} 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci/* 79662306a36Sopenharmony_ci * Determine the number of bytes of data the page contains 79762306a36Sopenharmony_ci */ 79862306a36Sopenharmony_cistatic inline 79962306a36Sopenharmony_ciunsigned int nfs_page_length(struct page *page) 80062306a36Sopenharmony_ci{ 80162306a36Sopenharmony_ci loff_t i_size = i_size_read(page_file_mapping(page)->host); 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci if (i_size > 0) { 80462306a36Sopenharmony_ci pgoff_t index = page_index(page); 80562306a36Sopenharmony_ci pgoff_t end_index = (i_size - 1) >> PAGE_SHIFT; 80662306a36Sopenharmony_ci if (index < end_index) 80762306a36Sopenharmony_ci return PAGE_SIZE; 80862306a36Sopenharmony_ci if (index == end_index) 80962306a36Sopenharmony_ci return ((i_size - 1) & ~PAGE_MASK) + 1; 81062306a36Sopenharmony_ci } 81162306a36Sopenharmony_ci return 0; 81262306a36Sopenharmony_ci} 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci/* 81562306a36Sopenharmony_ci * Determine the number of bytes of data the page contains 81662306a36Sopenharmony_ci */ 81762306a36Sopenharmony_cistatic inline size_t nfs_folio_length(struct folio *folio) 81862306a36Sopenharmony_ci{ 81962306a36Sopenharmony_ci loff_t i_size = i_size_read(folio_file_mapping(folio)->host); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci if (i_size > 0) { 82262306a36Sopenharmony_ci pgoff_t index = folio_index(folio) >> folio_order(folio); 82362306a36Sopenharmony_ci pgoff_t end_index = (i_size - 1) >> folio_shift(folio); 82462306a36Sopenharmony_ci if (index < end_index) 82562306a36Sopenharmony_ci return folio_size(folio); 82662306a36Sopenharmony_ci if (index == end_index) 82762306a36Sopenharmony_ci return offset_in_folio(folio, i_size - 1) + 1; 82862306a36Sopenharmony_ci } 82962306a36Sopenharmony_ci return 0; 83062306a36Sopenharmony_ci} 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci/* 83362306a36Sopenharmony_ci * Convert a umode to a dirent->d_type 83462306a36Sopenharmony_ci */ 83562306a36Sopenharmony_cistatic inline 83662306a36Sopenharmony_ciunsigned char nfs_umode_to_dtype(umode_t mode) 83762306a36Sopenharmony_ci{ 83862306a36Sopenharmony_ci return (mode >> 12) & 15; 83962306a36Sopenharmony_ci} 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci/* 84262306a36Sopenharmony_ci * Determine the number of pages in an array of length 'len' and 84362306a36Sopenharmony_ci * with a base offset of 'base' 84462306a36Sopenharmony_ci */ 84562306a36Sopenharmony_cistatic inline unsigned int nfs_page_array_len(unsigned int base, size_t len) 84662306a36Sopenharmony_ci{ 84762306a36Sopenharmony_ci return ((unsigned long)len + (unsigned long)base + PAGE_SIZE - 1) >> 84862306a36Sopenharmony_ci PAGE_SHIFT; 84962306a36Sopenharmony_ci} 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci/* 85262306a36Sopenharmony_ci * Convert a struct timespec64 into a 64-bit change attribute 85362306a36Sopenharmony_ci * 85462306a36Sopenharmony_ci * This does approximately the same thing as timespec64_to_ns(), 85562306a36Sopenharmony_ci * but for calculation efficiency, we multiply the seconds by 85662306a36Sopenharmony_ci * 1024*1024*1024. 85762306a36Sopenharmony_ci */ 85862306a36Sopenharmony_cistatic inline 85962306a36Sopenharmony_ciu64 nfs_timespec_to_change_attr(const struct timespec64 *ts) 86062306a36Sopenharmony_ci{ 86162306a36Sopenharmony_ci return ((u64)ts->tv_sec << 30) + ts->tv_nsec; 86262306a36Sopenharmony_ci} 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci#ifdef CONFIG_CRC32 86562306a36Sopenharmony_cistatic inline u32 nfs_stateid_hash(const nfs4_stateid *stateid) 86662306a36Sopenharmony_ci{ 86762306a36Sopenharmony_ci return ~crc32_le(0xFFFFFFFF, &stateid->other[0], 86862306a36Sopenharmony_ci NFS4_STATEID_OTHER_SIZE); 86962306a36Sopenharmony_ci} 87062306a36Sopenharmony_ci#else 87162306a36Sopenharmony_cistatic inline u32 nfs_stateid_hash(nfs4_stateid *stateid) 87262306a36Sopenharmony_ci{ 87362306a36Sopenharmony_ci return 0; 87462306a36Sopenharmony_ci} 87562306a36Sopenharmony_ci#endif 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_cistatic inline bool nfs_error_is_fatal(int err) 87862306a36Sopenharmony_ci{ 87962306a36Sopenharmony_ci switch (err) { 88062306a36Sopenharmony_ci case -ERESTARTSYS: 88162306a36Sopenharmony_ci case -EINTR: 88262306a36Sopenharmony_ci case -EACCES: 88362306a36Sopenharmony_ci case -EDQUOT: 88462306a36Sopenharmony_ci case -EFBIG: 88562306a36Sopenharmony_ci case -EIO: 88662306a36Sopenharmony_ci case -ENOSPC: 88762306a36Sopenharmony_ci case -EROFS: 88862306a36Sopenharmony_ci case -ESTALE: 88962306a36Sopenharmony_ci case -E2BIG: 89062306a36Sopenharmony_ci case -ENOMEM: 89162306a36Sopenharmony_ci case -ETIMEDOUT: 89262306a36Sopenharmony_ci return true; 89362306a36Sopenharmony_ci default: 89462306a36Sopenharmony_ci return false; 89562306a36Sopenharmony_ci } 89662306a36Sopenharmony_ci} 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_cistatic inline bool nfs_error_is_fatal_on_server(int err) 89962306a36Sopenharmony_ci{ 90062306a36Sopenharmony_ci switch (err) { 90162306a36Sopenharmony_ci case 0: 90262306a36Sopenharmony_ci case -ERESTARTSYS: 90362306a36Sopenharmony_ci case -EINTR: 90462306a36Sopenharmony_ci case -ENOMEM: 90562306a36Sopenharmony_ci return false; 90662306a36Sopenharmony_ci } 90762306a36Sopenharmony_ci return nfs_error_is_fatal(err); 90862306a36Sopenharmony_ci} 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci/* 91162306a36Sopenharmony_ci * Select between a default port value and a user-specified port value. 91262306a36Sopenharmony_ci * If a zero value is set, then autobind will be used. 91362306a36Sopenharmony_ci */ 91462306a36Sopenharmony_cistatic inline void nfs_set_port(struct sockaddr_storage *sap, int *port, 91562306a36Sopenharmony_ci const unsigned short default_port) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci if (*port == NFS_UNSPEC_PORT) 91862306a36Sopenharmony_ci *port = default_port; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci rpc_set_port((struct sockaddr *)sap, *port); 92162306a36Sopenharmony_ci} 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_cistruct nfs_direct_req { 92462306a36Sopenharmony_ci struct kref kref; /* release manager */ 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci /* I/O parameters */ 92762306a36Sopenharmony_ci struct nfs_open_context *ctx; /* file open context info */ 92862306a36Sopenharmony_ci struct nfs_lock_context *l_ctx; /* Lock context info */ 92962306a36Sopenharmony_ci struct kiocb * iocb; /* controlling i/o request */ 93062306a36Sopenharmony_ci struct inode * inode; /* target file of i/o */ 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci /* completion state */ 93362306a36Sopenharmony_ci atomic_t io_count; /* i/os we're waiting for */ 93462306a36Sopenharmony_ci spinlock_t lock; /* protect completion state */ 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci loff_t io_start; /* Start offset for I/O */ 93762306a36Sopenharmony_ci ssize_t count, /* bytes actually processed */ 93862306a36Sopenharmony_ci max_count, /* max expected count */ 93962306a36Sopenharmony_ci bytes_left, /* bytes left to be sent */ 94062306a36Sopenharmony_ci error; /* any reported error */ 94162306a36Sopenharmony_ci struct completion completion; /* wait for i/o completion */ 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci /* commit state */ 94462306a36Sopenharmony_ci struct nfs_mds_commit_info mds_cinfo; /* Storage for cinfo */ 94562306a36Sopenharmony_ci struct pnfs_ds_commit_info ds_cinfo; /* Storage for cinfo */ 94662306a36Sopenharmony_ci struct work_struct work; 94762306a36Sopenharmony_ci int flags; 94862306a36Sopenharmony_ci /* for write */ 94962306a36Sopenharmony_ci#define NFS_ODIRECT_DO_COMMIT (1) /* an unstable reply was received */ 95062306a36Sopenharmony_ci#define NFS_ODIRECT_RESCHED_WRITES (2) /* write verification failed */ 95162306a36Sopenharmony_ci /* for read */ 95262306a36Sopenharmony_ci#define NFS_ODIRECT_SHOULD_DIRTY (3) /* dirty user-space page after read */ 95362306a36Sopenharmony_ci#define NFS_ODIRECT_DONE INT_MAX /* write verification failed */ 95462306a36Sopenharmony_ci}; 955