11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/include/linux/nfs_page.h
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000 Trond Myklebust
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NFS page cache wrapper.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef _LINUX_NFS_PAGE_H
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _LINUX_NFS_PAGE_H
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/list.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pagemap.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/wait.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/auth.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/nfs_xdr.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19c03b40246123b2ced79e2620d1d2c089bb12369aTrond Myklebust#include <linux/kref.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Valid flags for a dirty buffer
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
24e468bae97d243fe0e1515abaa1f7d0edf1476ad0Trond Myklebustenum {
2512c05792599ec57ebab33096b2c75b863dfe6ea4Weston Andros Adamson	PG_BUSY = 0,		/* nfs_{un}lock_request */
2612c05792599ec57ebab33096b2c75b863dfe6ea4Weston Andros Adamson	PG_MAPPED,		/* page private set for buffered io */
2712c05792599ec57ebab33096b2c75b863dfe6ea4Weston Andros Adamson	PG_CLEAN,		/* write succeeded */
2812c05792599ec57ebab33096b2c75b863dfe6ea4Weston Andros Adamson	PG_COMMIT_TO_DS,	/* used by pnfs layouts */
29b412ddf0661e11485876a202c48868143e3a01cfWeston Andros Adamson	PG_INODE_REF,		/* extra ref held by inode when in writeback */
302bfc6e566daa8386c9cffef2f7de17fc330d3835Weston Andros Adamson	PG_HEADLOCK,		/* page group lock of wb_head */
312bfc6e566daa8386c9cffef2f7de17fc330d3835Weston Andros Adamson	PG_TEARDOWN,		/* page group sync for destroy */
3267d0338edd71db9a4f406d8778f7c525d31e9f7fWeston Andros Adamson	PG_UNLOCKPAGE,		/* page group sync bit in read path */
3367d0338edd71db9a4f406d8778f7c525d31e9f7fWeston Andros Adamson	PG_UPTODATE,		/* page group sync bit in read path */
3420633f042fd0907300069714b98aaf607a8b5bf8Weston Andros Adamson	PG_WB_END,		/* page group sync bit in write path */
3520633f042fd0907300069714b98aaf607a8b5bf8Weston Andros Adamson	PG_REMOVE,		/* page group sync bit in write path */
36e468bae97d243fe0e1515abaa1f7d0edf1476ad0Trond Myklebust};
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
383da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebuststruct nfs_inode;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct nfs_page {
40d6d6dc7cdfda7c8f49a89a7b7261846f319da6d1Fred Isaman	struct list_head	wb_list;	/* Defines state of page: */
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page		*wb_page;	/* page to read in/write out */
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nfs_open_context	*wb_context;	/* File state context info */
43f11ac8db5d07b6e99d41ff4aa39d878ee5cef1c5Trond Myklebust	struct nfs_lock_context	*wb_lock_context;	/* lock context info */
44ca52fec152282ef73e5e882b847b36b1febbb1c6Trond Myklebust	pgoff_t			wb_index;	/* Offset >> PAGE_CACHE_SHIFT */
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int		wb_offset,	/* Offset & ~PAGE_CACHE_MASK */
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				wb_pgbase,	/* Start of page data */
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				wb_bytes;	/* Length of request */
48c03b40246123b2ced79e2620d1d2c089bb12369aTrond Myklebust	struct kref		wb_kref;	/* reference count */
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		wb_flags;
502f2c63bc221c5fcded24de2704575d0abf96b910Trond Myklebust	struct nfs_write_verifier	wb_verf;	/* Commit cookie */
512bfc6e566daa8386c9cffef2f7de17fc330d3835Weston Andros Adamson	struct nfs_page		*wb_this_page;  /* list of reqs for this page */
522bfc6e566daa8386c9cffef2f7de17fc330d3835Weston Andros Adamson	struct nfs_page		*wb_head;       /* head pointer for req list */
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551751c3638f2a07a8c66a803a31791bab9bd3fcedTrond Myklebuststruct nfs_pageio_descriptor;
561751c3638f2a07a8c66a803a31791bab9bd3fcedTrond Myklebuststruct nfs_pageio_ops {
57d8007d4dd6ff8749cc8a4063c3ec87442db76d82Trond Myklebust	void	(*pg_init)(struct nfs_pageio_descriptor *, struct nfs_page *);
58b4fdac1a5150174df0847a45dc6612ce5ce3daebWeston Andros Adamson	size_t	(*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *,
59b4fdac1a5150174df0847a45dc6612ce5ce3daebWeston Andros Adamson			   struct nfs_page *);
601751c3638f2a07a8c66a803a31791bab9bd3fcedTrond Myklebust	int	(*pg_doio)(struct nfs_pageio_descriptor *);
611751c3638f2a07a8c66a803a31791bab9bd3fcedTrond Myklebust};
621751c3638f2a07a8c66a803a31791bab9bd3fcedTrond Myklebust
634a0de55c565a36cac8422b76a948c4634a90781eAnna Schumakerstruct nfs_rw_ops {
64a4cdda59111f92000297e0d3edb1e0e08ba3549bAnna Schumaker	const fmode_t rw_mode;
651e7f3a485922211b6e4a082ebc6bf05810b0b6eaWeston Andros Adamson	struct nfs_pgio_header *(*rw_alloc_header)(void);
661e7f3a485922211b6e4a082ebc6bf05810b0b6eaWeston Andros Adamson	void (*rw_free_header)(struct nfs_pgio_header *);
67d45f60c67848b9f19160692581d78e5b4757a000Weston Andros Adamson	void (*rw_release)(struct nfs_pgio_header *);
68d45f60c67848b9f19160692581d78e5b4757a000Weston Andros Adamson	int  (*rw_done)(struct rpc_task *, struct nfs_pgio_header *,
69d45f60c67848b9f19160692581d78e5b4757a000Weston Andros Adamson			struct inode *);
70d45f60c67848b9f19160692581d78e5b4757a000Weston Andros Adamson	void (*rw_result)(struct rpc_task *, struct nfs_pgio_header *);
71d45f60c67848b9f19160692581d78e5b4757a000Weston Andros Adamson	void (*rw_initiate)(struct nfs_pgio_header *, struct rpc_message *,
721ed26f33008e954a8e91d26f97d4380dea8145dbAnna Schumaker			    struct rpc_task_setup *, int);
734a0de55c565a36cac8422b76a948c4634a90781eAnna Schumaker};
744a0de55c565a36cac8422b76a948c4634a90781eAnna Schumaker
75d8a5ad75cc4d577987964e37a4c43b1c648c201eTrond Myklebuststruct nfs_pageio_descriptor {
76d8a5ad75cc4d577987964e37a4c43b1c648c201eTrond Myklebust	struct list_head	pg_list;
77bcb71bba7e64f0442d0ca339d7d3117a7060589fTrond Myklebust	unsigned long		pg_bytes_written;
78d8a5ad75cc4d577987964e37a4c43b1c648c201eTrond Myklebust	size_t			pg_count;
79d8a5ad75cc4d577987964e37a4c43b1c648c201eTrond Myklebust	size_t			pg_bsize;
80d8a5ad75cc4d577987964e37a4c43b1c648c201eTrond Myklebust	unsigned int		pg_base;
81d9156f9f364897e93bdd98b4ad22138de18f7c24Trond Myklebust	unsigned char		pg_moreio : 1,
82d9156f9f364897e93bdd98b4ad22138de18f7c24Trond Myklebust				pg_recoalesce : 1;
83bcb71bba7e64f0442d0ca339d7d3117a7060589fTrond Myklebust
84bcb71bba7e64f0442d0ca339d7d3117a7060589fTrond Myklebust	struct inode		*pg_inode;
851751c3638f2a07a8c66a803a31791bab9bd3fcedTrond Myklebust	const struct nfs_pageio_ops *pg_ops;
864a0de55c565a36cac8422b76a948c4634a90781eAnna Schumaker	const struct nfs_rw_ops *pg_rw_ops;
87bcb71bba7e64f0442d0ca339d7d3117a7060589fTrond Myklebust	int 			pg_ioflags;
88bcb71bba7e64f0442d0ca339d7d3117a7060589fTrond Myklebust	int			pg_error;
8950828d7e6767a92726708bc0666e2b8b84575808Trond Myklebust	const struct rpc_call_ops *pg_rpc_callops;
90061ae2edb7375ab6776468b075da71008a098b55Fred Isaman	const struct nfs_pgio_completion_ops *pg_completion_ops;
9194ad1c80e28f9700c84b4d28d1e5302ddf63a6fdFred Isaman	struct pnfs_layout_segment *pg_lseg;
92584aa810b6240d88c28113a90c5029449814a3b5Fred Isaman	struct nfs_direct_req	*pg_dreq;
93f6166384095b7ecf77752b5e9096e6d03d75f7aePeng Tao	void			*pg_layout_private;
94d8a5ad75cc4d577987964e37a4c43b1c648c201eTrond Myklebust};
95d8a5ad75cc4d577987964e37a4c43b1c648c201eTrond Myklebust
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NFS_WBACK_BUSY(req)	(test_bit(PG_BUSY,&(req)->wb_flags))
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern	struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    struct page *page,
1002bfc6e566daa8386c9cffef2f7de17fc330d3835Weston Andros Adamson					    struct nfs_page *last,
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    unsigned int offset,
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    unsigned int count);
1032bfc6e566daa8386c9cffef2f7de17fc330d3835Weston Andros Adamsonextern	void nfs_release_request(struct nfs_page *);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
106bcb71bba7e64f0442d0ca339d7d3117a7060589fTrond Myklebustextern	void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
107bcb71bba7e64f0442d0ca339d7d3117a7060589fTrond Myklebust			     struct inode *inode,
1081751c3638f2a07a8c66a803a31791bab9bd3fcedTrond Myklebust			     const struct nfs_pageio_ops *pg_ops,
109061ae2edb7375ab6776468b075da71008a098b55Fred Isaman			     const struct nfs_pgio_completion_ops *compl_ops,
1104a0de55c565a36cac8422b76a948c4634a90781eAnna Schumaker			     const struct nfs_rw_ops *rw_ops,
111bcb71bba7e64f0442d0ca339d7d3117a7060589fTrond Myklebust			     size_t bsize,
112bcb71bba7e64f0442d0ca339d7d3117a7060589fTrond Myklebust			     int how);
1138b09bee3083897e375bd0bf9d60f48daedfab3e0Trond Myklebustextern	int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
1148b09bee3083897e375bd0bf9d60f48daedfab3e0Trond Myklebust				   struct nfs_page *);
11553113ad35e4b9ce82d949c7c67c7b666fad5d907Weston Andros Adamsonextern  int nfs_pageio_resend(struct nfs_pageio_descriptor *,
11653113ad35e4b9ce82d949c7c67c7b666fad5d907Weston Andros Adamson			      struct nfs_pgio_header *);
117bcb71bba7e64f0442d0ca339d7d3117a7060589fTrond Myklebustextern	void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
1187fe7f8487ae742239dd8c66596e2311c30d057d1Trond Myklebustextern	void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t);
119b4fdac1a5150174df0847a45dc6612ce5ce3daebWeston Andros Adamsonextern size_t nfs_generic_pg_test(struct nfs_pageio_descriptor *desc,
12019345cb299e8234006c5125151ab723e851a1d24Benny Halevy				struct nfs_page *prev,
12119345cb299e8234006c5125151ab723e851a1d24Benny Halevy				struct nfs_page *req);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern  int nfs_wait_on_request(struct nfs_page *);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern	void nfs_unlock_request(struct nfs_page *req);
1242bfc6e566daa8386c9cffef2f7de17fc330d3835Weston Andros Adamsonextern	void nfs_unlock_and_release_request(struct nfs_page *);
125e7029206ff43f6cf7d6fcb741adb126f47200516Weston Andros Adamsonextern int nfs_page_group_lock(struct nfs_page *, bool);
1267c3af975257383ece54b83c0505d3e0656cb7dafWeston Andros Adamsonextern void nfs_page_group_lock_wait(struct nfs_page *);
1272bfc6e566daa8386c9cffef2f7de17fc330d3835Weston Andros Adamsonextern void nfs_page_group_unlock(struct nfs_page *);
1282bfc6e566daa8386c9cffef2f7de17fc330d3835Weston Andros Adamsonextern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int);
129c6a556b88adfacd2af90be84357c8165d716c27dTrond Myklebust
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1317ad84aa9448571678c243f0c5ef383fbe5b50f4fTrond Myklebust * Lock the page of an asynchronous request
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
1348dd3775889345850ecddd689b5c200cdd91bd8c9Trond Myklebustnfs_lock_request(struct nfs_page *req)
1358dd3775889345850ecddd689b5c200cdd91bd8c9Trond Myklebust{
1367ad84aa9448571678c243f0c5ef383fbe5b50f4fTrond Myklebust	return !test_and_set_bit(PG_BUSY, &req->wb_flags);
1378dd3775889345850ecddd689b5c200cdd91bd8c9Trond Myklebust}
1388dd3775889345850ecddd689b5c200cdd91bd8c9Trond Myklebust
1393da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebust/**
1403da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebust * nfs_list_add_request - Insert a request into a list
1413da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebust * @req: request
1423da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebust * @head: head of list into which to insert the request.
1433da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebust */
1443da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebuststatic inline void
1453da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebustnfs_list_add_request(struct nfs_page *req, struct list_head *head)
1463da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebust{
1473da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebust	list_add_tail(&req->wb_list, head);
1483da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebust}
1493da28eb1c6545fe73263a24eba0996217490e1ebTrond Myklebust
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nfs_list_remove_request - Remove a request from its wb_list
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @req: request
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnfs_list_remove_request(struct nfs_page *req)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (list_empty(&req->wb_list))
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_del_init(&req->wb_list);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline struct nfs_page *
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnfs_list_entry(struct list_head *head)
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return list_entry(head, struct nfs_page, wb_list);
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsloff_t req_offset(struct nfs_page *req)
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (((loff_t)req->wb_index) << PAGE_CACHE_SHIFT) + req->wb_offset;
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* _LINUX_NFS_PAGE_H */
176