xref: /openbmc/linux/fs/nfs/internal.h (revision d8cb1a7c)
1f7b422b1SDavid Howells /*
2f7b422b1SDavid Howells  * NFS internal definitions
3f7b422b1SDavid Howells  */
4f7b422b1SDavid Howells 
5eedc020eSAndy Adamson #include "nfs4_fs.h"
6f7b422b1SDavid Howells #include <linux/mount.h>
7f9c3a380SEric Paris #include <linux/security.h>
8f7b422b1SDavid Howells 
908734048SDavid Howells #define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)
1008734048SDavid Howells 
1154ceac45SDavid Howells struct nfs_string;
1254ceac45SDavid Howells 
1354ceac45SDavid Howells /* Maximum number of readahead requests
1454ceac45SDavid Howells  * FIXME: this should really be a sysctl so that users may tune it to suit
1554ceac45SDavid Howells  *        their needs. People that do NFS over a slow network, might for
1654ceac45SDavid Howells  *        instance want to reduce it to something closer to 1 for improved
1754ceac45SDavid Howells  *        interactive response.
1854ceac45SDavid Howells  */
1954ceac45SDavid Howells #define NFS_MAX_READAHEAD	(RPC_DEF_SLOT_TABLE - 1)
2054ceac45SDavid Howells 
21eedc020eSAndy Adamson /*
22eedc020eSAndy Adamson  * Determine if sessions are in use.
23eedc020eSAndy Adamson  */
24eedc020eSAndy Adamson static inline int nfs4_has_session(const struct nfs_client *clp)
25eedc020eSAndy Adamson {
26eedc020eSAndy Adamson #ifdef CONFIG_NFS_V4_1
27eedc020eSAndy Adamson 	if (clp->cl_session)
28eedc020eSAndy Adamson 		return 1;
29eedc020eSAndy Adamson #endif /* CONFIG_NFS_V4_1 */
30eedc020eSAndy Adamson 	return 0;
31eedc020eSAndy Adamson }
32eedc020eSAndy Adamson 
33d8cb1a7cSAlexandros Batsakis static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
34d8cb1a7cSAlexandros Batsakis {
35d8cb1a7cSAlexandros Batsakis #ifdef CONFIG_NFS_V4_1
36d8cb1a7cSAlexandros Batsakis 	if (nfs4_has_session(clp))
37d8cb1a7cSAlexandros Batsakis 		return (clp->cl_session->flags & SESSION4_PERSIST);
38d8cb1a7cSAlexandros Batsakis #endif /* CONFIG_NFS_V4_1 */
39d8cb1a7cSAlexandros Batsakis 	return 0;
40d8cb1a7cSAlexandros Batsakis }
41d8cb1a7cSAlexandros Batsakis 
42f7b422b1SDavid Howells struct nfs_clone_mount {
43f7b422b1SDavid Howells 	const struct super_block *sb;
44f7b422b1SDavid Howells 	const struct dentry *dentry;
45f7b422b1SDavid Howells 	struct nfs_fh *fh;
46f7b422b1SDavid Howells 	struct nfs_fattr *fattr;
47f7b422b1SDavid Howells 	char *hostname;
48f7b422b1SDavid Howells 	char *mnt_path;
496677d095SChuck Lever 	struct sockaddr *addr;
506677d095SChuck Lever 	size_t addrlen;
51f7b422b1SDavid Howells 	rpc_authflavor_t authflavor;
52f7b422b1SDavid Howells };
53f7b422b1SDavid Howells 
546b18eaa0S\"Talpey, Thomas\ /*
55a14017dbSChuck Lever  * Note: RFC 1813 doesn't limit the number of auth flavors that
56a14017dbSChuck Lever  * a server can return, so make something up.
57a14017dbSChuck Lever  */
58a14017dbSChuck Lever #define NFS_MAX_SECFLAVORS	(12)
59a14017dbSChuck Lever 
60a14017dbSChuck Lever /*
614cfd74fcSChuck Lever  * Value used if the user did not specify a port value.
624cfd74fcSChuck Lever  */
634cfd74fcSChuck Lever #define NFS_UNSPEC_PORT		(-1)
644cfd74fcSChuck Lever 
654cfd74fcSChuck Lever /*
666b18eaa0S\"Talpey, Thomas\  * In-kernel mount arguments
676b18eaa0S\"Talpey, Thomas\  */
686b18eaa0S\"Talpey, Thomas\ struct nfs_parsed_mount_data {
696b18eaa0S\"Talpey, Thomas\ 	int			flags;
706b18eaa0S\"Talpey, Thomas\ 	int			rsize, wsize;
716b18eaa0S\"Talpey, Thomas\ 	int			timeo, retrans;
726b18eaa0S\"Talpey, Thomas\ 	int			acregmin, acregmax,
736b18eaa0S\"Talpey, Thomas\ 				acdirmin, acdirmax;
746b18eaa0S\"Talpey, Thomas\ 	int			namlen;
75b797cac7SDavid Howells 	unsigned int		options;
766b18eaa0S\"Talpey, Thomas\ 	unsigned int		bsize;
776b18eaa0S\"Talpey, Thomas\ 	unsigned int		auth_flavor_len;
786b18eaa0S\"Talpey, Thomas\ 	rpc_authflavor_t	auth_flavors[1];
796b18eaa0S\"Talpey, Thomas\ 	char			*client_address;
80764302ccSChuck Lever 	unsigned int		version;
813fd5be9eSMike Sager 	unsigned int		minorversion;
8208734048SDavid Howells 	char			*fscache_uniq;
836b18eaa0S\"Talpey, Thomas\ 
846b18eaa0S\"Talpey, Thomas\ 	struct {
854c568017SChuck Lever 		struct sockaddr_storage	address;
864c568017SChuck Lever 		size_t			addrlen;
876b18eaa0S\"Talpey, Thomas\ 		char			*hostname;
8878fa701fSChuck Lever 		u32			version;
894cfd74fcSChuck Lever 		int			port;
9078fa701fSChuck Lever 		unsigned short		protocol;
916b18eaa0S\"Talpey, Thomas\ 	} mount_server;
926b18eaa0S\"Talpey, Thomas\ 
936b18eaa0S\"Talpey, Thomas\ 	struct {
944c568017SChuck Lever 		struct sockaddr_storage	address;
954c568017SChuck Lever 		size_t			addrlen;
966b18eaa0S\"Talpey, Thomas\ 		char			*hostname;
976b18eaa0S\"Talpey, Thomas\ 		char			*export_path;
984cfd74fcSChuck Lever 		int			port;
9978fa701fSChuck Lever 		unsigned short		protocol;
1006b18eaa0S\"Talpey, Thomas\ 	} nfs_server;
101f9c3a380SEric Paris 
102f9c3a380SEric Paris 	struct security_mnt_opts lsm_opts;
1036b18eaa0S\"Talpey, Thomas\ };
1046b18eaa0S\"Talpey, Thomas\ 
105146ec944SChuck Lever /* mount_clnt.c */
106c5d120f8SChuck Lever struct nfs_mount_request {
107c5d120f8SChuck Lever 	struct sockaddr		*sap;
108c5d120f8SChuck Lever 	size_t			salen;
109c5d120f8SChuck Lever 	char			*hostname;
110c5d120f8SChuck Lever 	char			*dirpath;
111c5d120f8SChuck Lever 	u32			version;
112c5d120f8SChuck Lever 	unsigned short		protocol;
113c5d120f8SChuck Lever 	struct nfs_fh		*fh;
11450a737f8SChuck Lever 	int			noresvport;
1158e02f6b9SChuck Lever 	unsigned int		*auth_flav_len;
1168e02f6b9SChuck Lever 	rpc_authflavor_t	*auth_flavs;
117c5d120f8SChuck Lever };
118c5d120f8SChuck Lever 
119c5d120f8SChuck Lever extern int nfs_mount(struct nfs_mount_request *info);
1200b524123SChuck Lever extern void nfs_umount(const struct nfs_mount_request *info);
121146ec944SChuck Lever 
12224c8dbbbSDavid Howells /* client.c */
12354ceac45SDavid Howells extern struct rpc_program nfs_program;
12454ceac45SDavid Howells 
12524c8dbbbSDavid Howells extern void nfs_put_client(struct nfs_client *);
126ff052645SChuck Lever extern struct nfs_client *nfs_find_client(const struct sockaddr *, u32);
1273fbd67adSTrond Myklebust extern struct nfs_client *nfs_find_client_next(struct nfs_client *);
1282283f8d6S\"Talpey, Thomas\ extern struct nfs_server *nfs_create_server(
1292283f8d6S\"Talpey, Thomas\ 					const struct nfs_parsed_mount_data *,
13054ceac45SDavid Howells 					struct nfs_fh *);
13191ea40b9S\"Talpey, Thomas\ extern struct nfs_server *nfs4_create_server(
13291ea40b9S\"Talpey, Thomas\ 					const struct nfs_parsed_mount_data *,
13354ceac45SDavid Howells 					struct nfs_fh *);
13454ceac45SDavid Howells extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
13554ceac45SDavid Howells 						      struct nfs_fh *);
13654ceac45SDavid Howells extern void nfs_free_server(struct nfs_server *server);
13754ceac45SDavid Howells extern struct nfs_server *nfs_clone_server(struct nfs_server *,
13854ceac45SDavid Howells 					   struct nfs_fh *,
13954ceac45SDavid Howells 					   struct nfs_fattr *);
14076db6d95SAndy Adamson extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
141008f55d0SBenny Halevy extern int nfs4_check_client_ready(struct nfs_client *clp);
1426aaca566SDavid Howells #ifdef CONFIG_PROC_FS
1436aaca566SDavid Howells extern int __init nfs_fs_proc_init(void);
1446aaca566SDavid Howells extern void nfs_fs_proc_exit(void);
1456aaca566SDavid Howells #else
1466aaca566SDavid Howells static inline int nfs_fs_proc_init(void)
1476aaca566SDavid Howells {
1486aaca566SDavid Howells 	return 0;
1496aaca566SDavid Howells }
1506aaca566SDavid Howells static inline void nfs_fs_proc_exit(void)
1516aaca566SDavid Howells {
1526aaca566SDavid Howells }
1536aaca566SDavid Howells #endif
15424c8dbbbSDavid Howells 
1557d4e2747SDavid Howells /* nfs4namespace.c */
156f7b422b1SDavid Howells #ifdef CONFIG_NFS_V4
157f7b422b1SDavid Howells extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry);
158f7b422b1SDavid Howells #else
159f7b422b1SDavid Howells static inline
160f7b422b1SDavid Howells struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
161f7b422b1SDavid Howells {
162f7b422b1SDavid Howells 	return ERR_PTR(-ENOENT);
163f7b422b1SDavid Howells }
164f7b422b1SDavid Howells #endif
165f7b422b1SDavid Howells 
166f7b422b1SDavid Howells /* callback_xdr.c */
167f7b422b1SDavid Howells extern struct svc_version nfs4_callback_version1;
16807bccc2dSAlexandros Batsakis extern struct svc_version nfs4_callback_version4;
169f7b422b1SDavid Howells 
170f7b422b1SDavid Howells /* pagelist.c */
171f7b422b1SDavid Howells extern int __init nfs_init_nfspagecache(void);
172266bee88SDavid Brownell extern void nfs_destroy_nfspagecache(void);
173f7b422b1SDavid Howells extern int __init nfs_init_readpagecache(void);
174266bee88SDavid Brownell extern void nfs_destroy_readpagecache(void);
175f7b422b1SDavid Howells extern int __init nfs_init_writepagecache(void);
176266bee88SDavid Brownell extern void nfs_destroy_writepagecache(void);
177f7b422b1SDavid Howells 
178f7b422b1SDavid Howells extern int __init nfs_init_directcache(void);
179266bee88SDavid Brownell extern void nfs_destroy_directcache(void);
180f7b422b1SDavid Howells 
181f7b422b1SDavid Howells /* nfs2xdr.c */
1827d4e2747SDavid Howells extern int nfs_stat_to_errno(int);
183f7b422b1SDavid Howells extern struct rpc_procinfo nfs_procedures[];
1840dbb4c67SAl Viro extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
185f7b422b1SDavid Howells 
186f7b422b1SDavid Howells /* nfs3xdr.c */
187f7b422b1SDavid Howells extern struct rpc_procinfo nfs3_procedures[];
1880dbb4c67SAl Viro extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
189f7b422b1SDavid Howells 
190f7b422b1SDavid Howells /* nfs4xdr.c */
1917d4e2747SDavid Howells #ifdef CONFIG_NFS_V4
1920dbb4c67SAl Viro extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
1937d4e2747SDavid Howells #endif
194f7b422b1SDavid Howells 
195f7b422b1SDavid Howells /* nfs4proc.c */
196e608e79fSAndy Adamson extern void nfs4_restart_rpc(struct rpc_task *, const struct nfs_client *,
197e608e79fSAndy Adamson 			     struct nfs4_sequence_res *);
198d75d5414SAndrew Morton #ifdef CONFIG_NFS_V4
199f7b422b1SDavid Howells extern struct rpc_procinfo nfs4_procedures[];
200d75d5414SAndrew Morton #endif
201f7b422b1SDavid Howells 
2027fe5c398STrond Myklebust /* proc.c */
2037fe5c398STrond Myklebust void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
2047fe5c398STrond Myklebust 
205979df72eSTrond Myklebust /* dir.c */
206979df72eSTrond Myklebust extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask);
207979df72eSTrond Myklebust 
208f7b422b1SDavid Howells /* inode.c */
2095746006fSTrond Myklebust extern struct workqueue_struct *nfsiod_workqueue;
210f7b422b1SDavid Howells extern struct inode *nfs_alloc_inode(struct super_block *sb);
211f7b422b1SDavid Howells extern void nfs_destroy_inode(struct inode *);
212f7b422b1SDavid Howells extern int nfs_write_inode(struct inode *,int);
213f7b422b1SDavid Howells extern void nfs_clear_inode(struct inode *);
214f7b422b1SDavid Howells #ifdef CONFIG_NFS_V4
215f7b422b1SDavid Howells extern void nfs4_clear_inode(struct inode *);
216f7b422b1SDavid Howells #endif
217f41f7418STrond Myklebust void nfs_zap_acl_cache(struct inode *inode);
21872cb77f4STrond Myklebust extern int nfs_wait_bit_killable(void *word);
219f7b422b1SDavid Howells 
220f7b422b1SDavid Howells /* super.c */
22154ceac45SDavid Howells extern struct file_system_type nfs_xdev_fs_type;
222f7b422b1SDavid Howells #ifdef CONFIG_NFS_V4
22354ceac45SDavid Howells extern struct file_system_type nfs4_xdev_fs_type;
22454ceac45SDavid Howells extern struct file_system_type nfs4_referral_fs_type;
225f7b422b1SDavid Howells #endif
2264ebd9ab3SDominik Hackl 
227f7b422b1SDavid Howells extern struct rpc_stat nfs_rpcstat;
2284ebd9ab3SDominik Hackl 
229f7b422b1SDavid Howells extern int __init register_nfs_fs(void);
230f7b422b1SDavid Howells extern void __exit unregister_nfs_fs(void);
2311daef0a8STrond Myklebust extern void nfs_sb_active(struct super_block *sb);
2321daef0a8STrond Myklebust extern void nfs_sb_deactive(struct super_block *sb);
233f7b422b1SDavid Howells 
234f7b422b1SDavid Howells /* namespace.c */
23554ceac45SDavid Howells extern char *nfs_path(const char *base,
23654ceac45SDavid Howells 		      const struct dentry *droot,
23754ceac45SDavid Howells 		      const struct dentry *dentry,
238f7b422b1SDavid Howells 		      char *buffer, ssize_t buflen);
239f7b422b1SDavid Howells 
24054ceac45SDavid Howells /* getroot.c */
24154ceac45SDavid Howells extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *);
2427d4e2747SDavid Howells #ifdef CONFIG_NFS_V4
24354ceac45SDavid Howells extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *);
24454ceac45SDavid Howells 
24554ceac45SDavid Howells extern int nfs4_path_walk(struct nfs_server *server,
24654ceac45SDavid Howells 			  struct nfs_fh *mntfh,
24754ceac45SDavid Howells 			  const char *path);
2487d4e2747SDavid Howells #endif
249f7b422b1SDavid Howells 
250f11c88afSAndy Adamson /* read.c */
251f11c88afSAndy Adamson extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
252f11c88afSAndy Adamson 
253def6ed7eSAndy Adamson /* write.c */
254def6ed7eSAndy Adamson extern void nfs_write_prepare(struct rpc_task *task, void *calldata);
255074cc1deSTrond Myklebust #ifdef CONFIG_MIGRATION
256074cc1deSTrond Myklebust extern int nfs_migrate_page(struct address_space *,
257074cc1deSTrond Myklebust 		struct page *, struct page *);
258074cc1deSTrond Myklebust #else
259074cc1deSTrond Myklebust #define nfs_migrate_page NULL
260074cc1deSTrond Myklebust #endif
261def6ed7eSAndy Adamson 
262cccef3b9SAndy Adamson /* nfs4proc.c */
263cccef3b9SAndy Adamson extern int _nfs4_call_sync(struct nfs_server *server,
264cccef3b9SAndy Adamson 			   struct rpc_message *msg,
265cccef3b9SAndy Adamson 			   struct nfs4_sequence_args *args,
266cccef3b9SAndy Adamson 			   struct nfs4_sequence_res *res,
267cccef3b9SAndy Adamson 			   int cache_reply);
268cccef3b9SAndy Adamson extern int _nfs4_call_sync_session(struct nfs_server *server,
269cccef3b9SAndy Adamson 				   struct rpc_message *msg,
270cccef3b9SAndy Adamson 				   struct nfs4_sequence_args *args,
271cccef3b9SAndy Adamson 				   struct nfs4_sequence_res *res,
272cccef3b9SAndy Adamson 				   int cache_reply);
273cccef3b9SAndy Adamson 
27413615871SAndy Adamson #ifdef CONFIG_NFS_V4_1
27513615871SAndy Adamson extern void nfs41_sequence_free_slot(const struct nfs_client *,
27613615871SAndy Adamson 				     struct nfs4_sequence_res *res);
27713615871SAndy Adamson #endif /* CONFIG_NFS_V4_1 */
27813615871SAndy Adamson 
27913615871SAndy Adamson static inline void nfs4_sequence_free_slot(const struct nfs_client *clp,
28013615871SAndy Adamson 					   struct nfs4_sequence_res *res)
28113615871SAndy Adamson {
28213615871SAndy Adamson #ifdef CONFIG_NFS_V4_1
28313615871SAndy Adamson 	if (nfs4_has_session(clp))
28413615871SAndy Adamson 		nfs41_sequence_free_slot(clp, res);
28513615871SAndy Adamson #endif /* CONFIG_NFS_V4_1 */
28613615871SAndy Adamson }
28713615871SAndy Adamson 
288557134a3SAndy Adamson /*
289f7b422b1SDavid Howells  * Determine the device name as a string
290f7b422b1SDavid Howells  */
291f7b422b1SDavid Howells static inline char *nfs_devname(const struct vfsmount *mnt_parent,
292f7b422b1SDavid Howells 				const struct dentry *dentry,
293f7b422b1SDavid Howells 				char *buffer, ssize_t buflen)
294f7b422b1SDavid Howells {
29554ceac45SDavid Howells 	return nfs_path(mnt_parent->mnt_devname, mnt_parent->mnt_root,
29654ceac45SDavid Howells 			dentry, buffer, buflen);
297f7b422b1SDavid Howells }
298f7b422b1SDavid Howells 
299f7b422b1SDavid Howells /*
300f7b422b1SDavid Howells  * Determine the actual block size (and log2 thereof)
301f7b422b1SDavid Howells  */
302f7b422b1SDavid Howells static inline
303f7b422b1SDavid Howells unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp)
304f7b422b1SDavid Howells {
305f7b422b1SDavid Howells 	/* make sure blocksize is a power of two */
306f7b422b1SDavid Howells 	if ((bsize & (bsize - 1)) || nrbitsp) {
307f7b422b1SDavid Howells 		unsigned char	nrbits;
308f7b422b1SDavid Howells 
309f7b422b1SDavid Howells 		for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--)
310f7b422b1SDavid Howells 			;
311f7b422b1SDavid Howells 		bsize = 1 << nrbits;
312f7b422b1SDavid Howells 		if (nrbitsp)
313f7b422b1SDavid Howells 			*nrbitsp = nrbits;
314f7b422b1SDavid Howells 	}
315f7b422b1SDavid Howells 
316f7b422b1SDavid Howells 	return bsize;
317f7b422b1SDavid Howells }
318f7b422b1SDavid Howells 
319f7b422b1SDavid Howells /*
320f7b422b1SDavid Howells  * Calculate the number of 512byte blocks used.
321f7b422b1SDavid Howells  */
3229eaa67c6SChuck Lever static inline blkcnt_t nfs_calc_block_size(u64 tsize)
323f7b422b1SDavid Howells {
3249eaa67c6SChuck Lever 	blkcnt_t used = (tsize + 511) >> 9;
325f7b422b1SDavid Howells 	return (used > ULONG_MAX) ? ULONG_MAX : used;
326f7b422b1SDavid Howells }
327f7b422b1SDavid Howells 
328f7b422b1SDavid Howells /*
329f7b422b1SDavid Howells  * Compute and set NFS server blocksize
330f7b422b1SDavid Howells  */
331f7b422b1SDavid Howells static inline
332f7b422b1SDavid Howells unsigned long nfs_block_size(unsigned long bsize, unsigned char *nrbitsp)
333f7b422b1SDavid Howells {
334f7b422b1SDavid Howells 	if (bsize < NFS_MIN_FILE_IO_SIZE)
335f7b422b1SDavid Howells 		bsize = NFS_DEF_FILE_IO_SIZE;
336f7b422b1SDavid Howells 	else if (bsize >= NFS_MAX_FILE_IO_SIZE)
337f7b422b1SDavid Howells 		bsize = NFS_MAX_FILE_IO_SIZE;
338f7b422b1SDavid Howells 
339f7b422b1SDavid Howells 	return nfs_block_bits(bsize, nrbitsp);
340f7b422b1SDavid Howells }
341f7b422b1SDavid Howells 
342f7b422b1SDavid Howells /*
343f7b422b1SDavid Howells  * Determine the maximum file size for a superblock
344f7b422b1SDavid Howells  */
345f7b422b1SDavid Howells static inline
346f7b422b1SDavid Howells void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize)
347f7b422b1SDavid Howells {
348f7b422b1SDavid Howells 	sb->s_maxbytes = (loff_t)maxfilesize;
349f7b422b1SDavid Howells 	if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0)
350f7b422b1SDavid Howells 		sb->s_maxbytes = MAX_LFS_FILESIZE;
351f7b422b1SDavid Howells }
35249a70f27STrond Myklebust 
35349a70f27STrond Myklebust /*
35449a70f27STrond Myklebust  * Determine the number of bytes of data the page contains
35549a70f27STrond Myklebust  */
35649a70f27STrond Myklebust static inline
35749a70f27STrond Myklebust unsigned int nfs_page_length(struct page *page)
35849a70f27STrond Myklebust {
35949a70f27STrond Myklebust 	loff_t i_size = i_size_read(page->mapping->host);
36049a70f27STrond Myklebust 
36149a70f27STrond Myklebust 	if (i_size > 0) {
36249a70f27STrond Myklebust 		pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
36349a70f27STrond Myklebust 		if (page->index < end_index)
36449a70f27STrond Myklebust 			return PAGE_CACHE_SIZE;
36549a70f27STrond Myklebust 		if (page->index == end_index)
36649a70f27STrond Myklebust 			return ((i_size - 1) & ~PAGE_CACHE_MASK) + 1;
36749a70f27STrond Myklebust 	}
36849a70f27STrond Myklebust 	return 0;
36949a70f27STrond Myklebust }
3708d5658c9STrond Myklebust 
3718d5658c9STrond Myklebust /*
3728d5658c9STrond Myklebust  * Determine the number of pages in an array of length 'len' and
3738d5658c9STrond Myklebust  * with a base offset of 'base'
3748d5658c9STrond Myklebust  */
3758d5658c9STrond Myklebust static inline
3768d5658c9STrond Myklebust unsigned int nfs_page_array_len(unsigned int base, size_t len)
3778d5658c9STrond Myklebust {
3788d5658c9STrond Myklebust 	return ((unsigned long)len + (unsigned long)base +
3798d5658c9STrond Myklebust 		PAGE_SIZE - 1) >> PAGE_SHIFT;
3808d5658c9STrond Myklebust }
381