1f7b422b1SDavid Howells /* 2f7b422b1SDavid Howells * NFS internal definitions 3f7b422b1SDavid Howells */ 4f7b422b1SDavid Howells 5f7b422b1SDavid Howells #include <linux/mount.h> 6f9c3a380SEric Paris #include <linux/security.h> 7f7b422b1SDavid Howells 808734048SDavid Howells #define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS) 908734048SDavid Howells 1054ceac45SDavid Howells struct nfs_string; 1154ceac45SDavid Howells 1254ceac45SDavid Howells /* Maximum number of readahead requests 1354ceac45SDavid Howells * FIXME: this should really be a sysctl so that users may tune it to suit 1454ceac45SDavid Howells * their needs. People that do NFS over a slow network, might for 1554ceac45SDavid Howells * instance want to reduce it to something closer to 1 for improved 1654ceac45SDavid Howells * interactive response. 1754ceac45SDavid Howells */ 1854ceac45SDavid Howells #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) 1954ceac45SDavid Howells 20f7b422b1SDavid Howells struct nfs_clone_mount { 21f7b422b1SDavid Howells const struct super_block *sb; 22f7b422b1SDavid Howells const struct dentry *dentry; 23f7b422b1SDavid Howells struct nfs_fh *fh; 24f7b422b1SDavid Howells struct nfs_fattr *fattr; 25f7b422b1SDavid Howells char *hostname; 26f7b422b1SDavid Howells char *mnt_path; 276677d095SChuck Lever struct sockaddr *addr; 286677d095SChuck Lever size_t addrlen; 29f7b422b1SDavid Howells rpc_authflavor_t authflavor; 30f7b422b1SDavid Howells }; 31f7b422b1SDavid Howells 326b18eaa0S\"Talpey, Thomas\ /* 336b18eaa0S\"Talpey, Thomas\ * In-kernel mount arguments 346b18eaa0S\"Talpey, Thomas\ */ 356b18eaa0S\"Talpey, Thomas\ struct nfs_parsed_mount_data { 366b18eaa0S\"Talpey, Thomas\ int flags; 376b18eaa0S\"Talpey, Thomas\ int rsize, wsize; 386b18eaa0S\"Talpey, Thomas\ int timeo, retrans; 396b18eaa0S\"Talpey, Thomas\ int acregmin, acregmax, 406b18eaa0S\"Talpey, Thomas\ acdirmin, acdirmax; 416b18eaa0S\"Talpey, Thomas\ int namlen; 42b797cac7SDavid Howells unsigned int options; 436b18eaa0S\"Talpey, Thomas\ unsigned int bsize; 446b18eaa0S\"Talpey, Thomas\ unsigned int auth_flavor_len; 456b18eaa0S\"Talpey, Thomas\ rpc_authflavor_t auth_flavors[1]; 466b18eaa0S\"Talpey, Thomas\ char *client_address; 473fd5be9eSMike Sager unsigned int minorversion; 4808734048SDavid Howells char *fscache_uniq; 496b18eaa0S\"Talpey, Thomas\ 506b18eaa0S\"Talpey, Thomas\ struct { 514c568017SChuck Lever struct sockaddr_storage address; 524c568017SChuck Lever size_t addrlen; 536b18eaa0S\"Talpey, Thomas\ char *hostname; 5478fa701fSChuck Lever u32 version; 556b18eaa0S\"Talpey, Thomas\ unsigned short port; 5678fa701fSChuck Lever unsigned short protocol; 576b18eaa0S\"Talpey, Thomas\ } mount_server; 586b18eaa0S\"Talpey, Thomas\ 596b18eaa0S\"Talpey, Thomas\ struct { 604c568017SChuck Lever struct sockaddr_storage address; 614c568017SChuck Lever size_t addrlen; 626b18eaa0S\"Talpey, Thomas\ char *hostname; 636b18eaa0S\"Talpey, Thomas\ char *export_path; 64f22d6d79SChuck Lever unsigned short port; 6578fa701fSChuck Lever unsigned short protocol; 666b18eaa0S\"Talpey, Thomas\ } nfs_server; 67f9c3a380SEric Paris 68f9c3a380SEric Paris struct security_mnt_opts lsm_opts; 696b18eaa0S\"Talpey, Thomas\ }; 706b18eaa0S\"Talpey, Thomas\ 71146ec944SChuck Lever /* mount_clnt.c */ 72c5d120f8SChuck Lever struct nfs_mount_request { 73c5d120f8SChuck Lever struct sockaddr *sap; 74c5d120f8SChuck Lever size_t salen; 75c5d120f8SChuck Lever char *hostname; 76c5d120f8SChuck Lever char *dirpath; 77c5d120f8SChuck Lever u32 version; 78c5d120f8SChuck Lever unsigned short protocol; 79c5d120f8SChuck Lever struct nfs_fh *fh; 8050a737f8SChuck Lever int noresvport; 81c5d120f8SChuck Lever }; 82c5d120f8SChuck Lever 83c5d120f8SChuck Lever extern int nfs_mount(struct nfs_mount_request *info); 84146ec944SChuck Lever 8524c8dbbbSDavid Howells /* client.c */ 8654ceac45SDavid Howells extern struct rpc_program nfs_program; 8754ceac45SDavid Howells 8824c8dbbbSDavid Howells extern void nfs_put_client(struct nfs_client *); 89ff052645SChuck Lever extern struct nfs_client *nfs_find_client(const struct sockaddr *, u32); 903fbd67adSTrond Myklebust extern struct nfs_client *nfs_find_client_next(struct nfs_client *); 912283f8d6S\"Talpey, Thomas\ extern struct nfs_server *nfs_create_server( 922283f8d6S\"Talpey, Thomas\ const struct nfs_parsed_mount_data *, 9354ceac45SDavid Howells struct nfs_fh *); 9491ea40b9S\"Talpey, Thomas\ extern struct nfs_server *nfs4_create_server( 9591ea40b9S\"Talpey, Thomas\ const struct nfs_parsed_mount_data *, 9654ceac45SDavid Howells struct nfs_fh *); 9754ceac45SDavid Howells extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, 9854ceac45SDavid Howells struct nfs_fh *); 9954ceac45SDavid Howells extern void nfs_free_server(struct nfs_server *server); 10054ceac45SDavid Howells extern struct nfs_server *nfs_clone_server(struct nfs_server *, 10154ceac45SDavid Howells struct nfs_fh *, 10254ceac45SDavid Howells struct nfs_fattr *); 1036aaca566SDavid Howells #ifdef CONFIG_PROC_FS 1046aaca566SDavid Howells extern int __init nfs_fs_proc_init(void); 1056aaca566SDavid Howells extern void nfs_fs_proc_exit(void); 1066aaca566SDavid Howells #else 1076aaca566SDavid Howells static inline int nfs_fs_proc_init(void) 1086aaca566SDavid Howells { 1096aaca566SDavid Howells return 0; 1106aaca566SDavid Howells } 1116aaca566SDavid Howells static inline void nfs_fs_proc_exit(void) 1126aaca566SDavid Howells { 1136aaca566SDavid Howells } 1146aaca566SDavid Howells #endif 11524c8dbbbSDavid Howells 1167d4e2747SDavid Howells /* nfs4namespace.c */ 117f7b422b1SDavid Howells #ifdef CONFIG_NFS_V4 118f7b422b1SDavid Howells extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry); 119f7b422b1SDavid Howells #else 120f7b422b1SDavid Howells static inline 121f7b422b1SDavid Howells struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) 122f7b422b1SDavid Howells { 123f7b422b1SDavid Howells return ERR_PTR(-ENOENT); 124f7b422b1SDavid Howells } 125f7b422b1SDavid Howells #endif 126f7b422b1SDavid Howells 127f7b422b1SDavid Howells /* callback_xdr.c */ 128f7b422b1SDavid Howells extern struct svc_version nfs4_callback_version1; 129f7b422b1SDavid Howells 130f7b422b1SDavid Howells /* pagelist.c */ 131f7b422b1SDavid Howells extern int __init nfs_init_nfspagecache(void); 132266bee88SDavid Brownell extern void nfs_destroy_nfspagecache(void); 133f7b422b1SDavid Howells extern int __init nfs_init_readpagecache(void); 134266bee88SDavid Brownell extern void nfs_destroy_readpagecache(void); 135f7b422b1SDavid Howells extern int __init nfs_init_writepagecache(void); 136266bee88SDavid Brownell extern void nfs_destroy_writepagecache(void); 137f7b422b1SDavid Howells 138f7b422b1SDavid Howells extern int __init nfs_init_directcache(void); 139266bee88SDavid Brownell extern void nfs_destroy_directcache(void); 140f7b422b1SDavid Howells 141f7b422b1SDavid Howells /* nfs2xdr.c */ 1427d4e2747SDavid Howells extern int nfs_stat_to_errno(int); 143f7b422b1SDavid Howells extern struct rpc_procinfo nfs_procedures[]; 1440dbb4c67SAl Viro extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int); 145f7b422b1SDavid Howells 146f7b422b1SDavid Howells /* nfs3xdr.c */ 147f7b422b1SDavid Howells extern struct rpc_procinfo nfs3_procedures[]; 1480dbb4c67SAl Viro extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int); 149f7b422b1SDavid Howells 150f7b422b1SDavid Howells /* nfs4xdr.c */ 1517d4e2747SDavid Howells #ifdef CONFIG_NFS_V4 1520dbb4c67SAl Viro extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus); 1537d4e2747SDavid Howells #endif 154f7b422b1SDavid Howells 155f7b422b1SDavid Howells /* nfs4proc.c */ 156d75d5414SAndrew Morton #ifdef CONFIG_NFS_V4 157f7b422b1SDavid Howells extern struct rpc_procinfo nfs4_procedures[]; 158d75d5414SAndrew Morton #endif 159f7b422b1SDavid Howells 1607fe5c398STrond Myklebust /* proc.c */ 1617fe5c398STrond Myklebust void nfs_close_context(struct nfs_open_context *ctx, int is_sync); 1627fe5c398STrond Myklebust 163979df72eSTrond Myklebust /* dir.c */ 164979df72eSTrond Myklebust extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); 165979df72eSTrond Myklebust 166f7b422b1SDavid Howells /* inode.c */ 1675746006fSTrond Myklebust extern struct workqueue_struct *nfsiod_workqueue; 168f7b422b1SDavid Howells extern struct inode *nfs_alloc_inode(struct super_block *sb); 169f7b422b1SDavid Howells extern void nfs_destroy_inode(struct inode *); 170f7b422b1SDavid Howells extern int nfs_write_inode(struct inode *,int); 171f7b422b1SDavid Howells extern void nfs_clear_inode(struct inode *); 172f7b422b1SDavid Howells #ifdef CONFIG_NFS_V4 173f7b422b1SDavid Howells extern void nfs4_clear_inode(struct inode *); 174f7b422b1SDavid Howells #endif 175f41f7418STrond Myklebust void nfs_zap_acl_cache(struct inode *inode); 17672cb77f4STrond Myklebust extern int nfs_wait_bit_killable(void *word); 177f7b422b1SDavid Howells 178f7b422b1SDavid Howells /* super.c */ 179ea31a443SJ. Bruce Fields void nfs_parse_ip_address(char *, size_t, struct sockaddr *, size_t *); 18054ceac45SDavid Howells extern struct file_system_type nfs_xdev_fs_type; 181f7b422b1SDavid Howells #ifdef CONFIG_NFS_V4 18254ceac45SDavid Howells extern struct file_system_type nfs4_xdev_fs_type; 18354ceac45SDavid Howells extern struct file_system_type nfs4_referral_fs_type; 184f7b422b1SDavid Howells #endif 1854ebd9ab3SDominik Hackl 186f7b422b1SDavid Howells extern struct rpc_stat nfs_rpcstat; 1874ebd9ab3SDominik Hackl 188f7b422b1SDavid Howells extern int __init register_nfs_fs(void); 189f7b422b1SDavid Howells extern void __exit unregister_nfs_fs(void); 1901daef0a8STrond Myklebust extern void nfs_sb_active(struct super_block *sb); 1911daef0a8STrond Myklebust extern void nfs_sb_deactive(struct super_block *sb); 192f7b422b1SDavid Howells 193f7b422b1SDavid Howells /* namespace.c */ 19454ceac45SDavid Howells extern char *nfs_path(const char *base, 19554ceac45SDavid Howells const struct dentry *droot, 19654ceac45SDavid Howells const struct dentry *dentry, 197f7b422b1SDavid Howells char *buffer, ssize_t buflen); 198f7b422b1SDavid Howells 19954ceac45SDavid Howells /* getroot.c */ 20054ceac45SDavid Howells extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *); 2017d4e2747SDavid Howells #ifdef CONFIG_NFS_V4 20254ceac45SDavid Howells extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); 20354ceac45SDavid Howells 20454ceac45SDavid Howells extern int nfs4_path_walk(struct nfs_server *server, 20554ceac45SDavid Howells struct nfs_fh *mntfh, 20654ceac45SDavid Howells const char *path); 2077d4e2747SDavid Howells #endif 208f7b422b1SDavid Howells 209cccef3b9SAndy Adamson /* nfs4proc.c */ 210cccef3b9SAndy Adamson extern int _nfs4_call_sync(struct nfs_server *server, 211cccef3b9SAndy Adamson struct rpc_message *msg, 212cccef3b9SAndy Adamson struct nfs4_sequence_args *args, 213cccef3b9SAndy Adamson struct nfs4_sequence_res *res, 214cccef3b9SAndy Adamson int cache_reply); 215cccef3b9SAndy Adamson extern int _nfs4_call_sync_session(struct nfs_server *server, 216cccef3b9SAndy Adamson struct rpc_message *msg, 217cccef3b9SAndy Adamson struct nfs4_sequence_args *args, 218cccef3b9SAndy Adamson struct nfs4_sequence_res *res, 219cccef3b9SAndy Adamson int cache_reply); 220cccef3b9SAndy Adamson 221f7b422b1SDavid Howells /* 222557134a3SAndy Adamson * Determine if sessions are in use. 223557134a3SAndy Adamson */ 224557134a3SAndy Adamson static inline int nfs4_has_session(const struct nfs_client *clp) 225557134a3SAndy Adamson { 226557134a3SAndy Adamson #ifdef CONFIG_NFS_V4_1 227557134a3SAndy Adamson if (clp->cl_session) 228557134a3SAndy Adamson return 1; 229557134a3SAndy Adamson #endif /* CONFIG_NFS_V4_1 */ 230557134a3SAndy Adamson return 0; 231557134a3SAndy Adamson } 232557134a3SAndy Adamson 233557134a3SAndy Adamson /* 234f7b422b1SDavid Howells * Determine the device name as a string 235f7b422b1SDavid Howells */ 236f7b422b1SDavid Howells static inline char *nfs_devname(const struct vfsmount *mnt_parent, 237f7b422b1SDavid Howells const struct dentry *dentry, 238f7b422b1SDavid Howells char *buffer, ssize_t buflen) 239f7b422b1SDavid Howells { 24054ceac45SDavid Howells return nfs_path(mnt_parent->mnt_devname, mnt_parent->mnt_root, 24154ceac45SDavid Howells dentry, buffer, buflen); 242f7b422b1SDavid Howells } 243f7b422b1SDavid Howells 244f7b422b1SDavid Howells /* 245f7b422b1SDavid Howells * Determine the actual block size (and log2 thereof) 246f7b422b1SDavid Howells */ 247f7b422b1SDavid Howells static inline 248f7b422b1SDavid Howells unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp) 249f7b422b1SDavid Howells { 250f7b422b1SDavid Howells /* make sure blocksize is a power of two */ 251f7b422b1SDavid Howells if ((bsize & (bsize - 1)) || nrbitsp) { 252f7b422b1SDavid Howells unsigned char nrbits; 253f7b422b1SDavid Howells 254f7b422b1SDavid Howells for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--) 255f7b422b1SDavid Howells ; 256f7b422b1SDavid Howells bsize = 1 << nrbits; 257f7b422b1SDavid Howells if (nrbitsp) 258f7b422b1SDavid Howells *nrbitsp = nrbits; 259f7b422b1SDavid Howells } 260f7b422b1SDavid Howells 261f7b422b1SDavid Howells return bsize; 262f7b422b1SDavid Howells } 263f7b422b1SDavid Howells 264f7b422b1SDavid Howells /* 265f7b422b1SDavid Howells * Calculate the number of 512byte blocks used. 266f7b422b1SDavid Howells */ 2679eaa67c6SChuck Lever static inline blkcnt_t nfs_calc_block_size(u64 tsize) 268f7b422b1SDavid Howells { 2699eaa67c6SChuck Lever blkcnt_t used = (tsize + 511) >> 9; 270f7b422b1SDavid Howells return (used > ULONG_MAX) ? ULONG_MAX : used; 271f7b422b1SDavid Howells } 272f7b422b1SDavid Howells 273f7b422b1SDavid Howells /* 274f7b422b1SDavid Howells * Compute and set NFS server blocksize 275f7b422b1SDavid Howells */ 276f7b422b1SDavid Howells static inline 277f7b422b1SDavid Howells unsigned long nfs_block_size(unsigned long bsize, unsigned char *nrbitsp) 278f7b422b1SDavid Howells { 279f7b422b1SDavid Howells if (bsize < NFS_MIN_FILE_IO_SIZE) 280f7b422b1SDavid Howells bsize = NFS_DEF_FILE_IO_SIZE; 281f7b422b1SDavid Howells else if (bsize >= NFS_MAX_FILE_IO_SIZE) 282f7b422b1SDavid Howells bsize = NFS_MAX_FILE_IO_SIZE; 283f7b422b1SDavid Howells 284f7b422b1SDavid Howells return nfs_block_bits(bsize, nrbitsp); 285f7b422b1SDavid Howells } 286f7b422b1SDavid Howells 287f7b422b1SDavid Howells /* 288f7b422b1SDavid Howells * Determine the maximum file size for a superblock 289f7b422b1SDavid Howells */ 290f7b422b1SDavid Howells static inline 291f7b422b1SDavid Howells void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) 292f7b422b1SDavid Howells { 293f7b422b1SDavid Howells sb->s_maxbytes = (loff_t)maxfilesize; 294f7b422b1SDavid Howells if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0) 295f7b422b1SDavid Howells sb->s_maxbytes = MAX_LFS_FILESIZE; 296f7b422b1SDavid Howells } 29749a70f27STrond Myklebust 29849a70f27STrond Myklebust /* 29949a70f27STrond Myklebust * Determine the number of bytes of data the page contains 30049a70f27STrond Myklebust */ 30149a70f27STrond Myklebust static inline 30249a70f27STrond Myklebust unsigned int nfs_page_length(struct page *page) 30349a70f27STrond Myklebust { 30449a70f27STrond Myklebust loff_t i_size = i_size_read(page->mapping->host); 30549a70f27STrond Myklebust 30649a70f27STrond Myklebust if (i_size > 0) { 30749a70f27STrond Myklebust pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; 30849a70f27STrond Myklebust if (page->index < end_index) 30949a70f27STrond Myklebust return PAGE_CACHE_SIZE; 31049a70f27STrond Myklebust if (page->index == end_index) 31149a70f27STrond Myklebust return ((i_size - 1) & ~PAGE_CACHE_MASK) + 1; 31249a70f27STrond Myklebust } 31349a70f27STrond Myklebust return 0; 31449a70f27STrond Myklebust } 3158d5658c9STrond Myklebust 3168d5658c9STrond Myklebust /* 3178d5658c9STrond Myklebust * Determine the number of pages in an array of length 'len' and 3188d5658c9STrond Myklebust * with a base offset of 'base' 3198d5658c9STrond Myklebust */ 3208d5658c9STrond Myklebust static inline 3218d5658c9STrond Myklebust unsigned int nfs_page_array_len(unsigned int base, size_t len) 3228d5658c9STrond Myklebust { 3238d5658c9STrond Myklebust return ((unsigned long)len + (unsigned long)base + 3248d5658c9STrond Myklebust PAGE_SIZE - 1) >> PAGE_SHIFT; 3258d5658c9STrond Myklebust } 3268d5658c9STrond Myklebust 327ea31a443SJ. Bruce Fields #define IPV6_SCOPE_DELIMITER '%' 328f0c92925SJ. Bruce Fields 329f0c92925SJ. Bruce Fields /* 330f0c92925SJ. Bruce Fields * Set the port number in an address. Be agnostic about the address 331f0c92925SJ. Bruce Fields * family. 332f0c92925SJ. Bruce Fields */ 333f0c92925SJ. Bruce Fields static inline void nfs_set_port(struct sockaddr *sap, unsigned short port) 334f0c92925SJ. Bruce Fields { 335f0c92925SJ. Bruce Fields struct sockaddr_in *ap = (struct sockaddr_in *)sap; 336456018d7SJ. Bruce Fields struct sockaddr_in6 *ap6 = (struct sockaddr_in6 *)sap; 337456018d7SJ. Bruce Fields 338456018d7SJ. Bruce Fields switch (sap->sa_family) { 339456018d7SJ. Bruce Fields case AF_INET: 340f0c92925SJ. Bruce Fields ap->sin_port = htons(port); 341f0c92925SJ. Bruce Fields break; 342456018d7SJ. Bruce Fields case AF_INET6: 343456018d7SJ. Bruce Fields ap6->sin6_port = htons(port); 344f0c92925SJ. Bruce Fields break; 345f0c92925SJ. Bruce Fields } 346f0c92925SJ. Bruce Fields } 347