Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */
2 : : /*
3 : : * linux/include/linux/nfs_page.h
4 : : *
5 : : * Copyright (C) 2000 Trond Myklebust
6 : : *
7 : : * NFS page cache wrapper.
8 : : */
9 : :
10 : : #ifndef _LINUX_NFS_PAGE_H
11 : : #define _LINUX_NFS_PAGE_H
12 : :
13 : :
14 : : #include <linux/list.h>
15 : : #include <linux/pagemap.h>
16 : : #include <linux/wait.h>
17 : : #include <linux/sunrpc/auth.h>
18 : : #include <linux/nfs_xdr.h>
19 : :
20 : : #include <linux/kref.h>
21 : :
22 : : /*
23 : : * Valid flags for a dirty buffer
24 : : */
25 : : enum {
26 : : PG_BUSY = 0, /* nfs_{un}lock_request */
27 : : PG_MAPPED, /* page private set for buffered io */
28 : : PG_CLEAN, /* write succeeded */
29 : : PG_COMMIT_TO_DS, /* used by pnfs layouts */
30 : : PG_INODE_REF, /* extra ref held by inode when in writeback */
31 : : PG_HEADLOCK, /* page group lock of wb_head */
32 : : PG_TEARDOWN, /* page group sync for destroy */
33 : : PG_UNLOCKPAGE, /* page group sync bit in read path */
34 : : PG_UPTODATE, /* page group sync bit in read path */
35 : : PG_WB_END, /* page group sync bit in write path */
36 : : PG_REMOVE, /* page group sync bit in write path */
37 : : PG_CONTENDED1, /* Is someone waiting for a lock? */
38 : : PG_CONTENDED2, /* Is someone waiting for a lock? */
39 : : };
40 : :
41 : : struct nfs_inode;
42 : : struct nfs_page {
43 : : struct list_head wb_list; /* Defines state of page: */
44 : : struct page *wb_page; /* page to read in/write out */
45 : : struct nfs_lock_context *wb_lock_context; /* lock context info */
46 : : pgoff_t wb_index; /* Offset >> PAGE_SHIFT */
47 : : unsigned int wb_offset, /* Offset & ~PAGE_MASK */
48 : : wb_pgbase, /* Start of page data */
49 : : wb_bytes; /* Length of request */
50 : : struct kref wb_kref; /* reference count */
51 : : unsigned long wb_flags;
52 : : struct nfs_write_verifier wb_verf; /* Commit cookie */
53 : : struct nfs_page *wb_this_page; /* list of reqs for this page */
54 : : struct nfs_page *wb_head; /* head pointer for req list */
55 : : unsigned short wb_nio; /* Number of I/O attempts */
56 : : };
57 : :
58 : : struct nfs_pageio_descriptor;
59 : : struct nfs_pageio_ops {
60 : : void (*pg_init)(struct nfs_pageio_descriptor *, struct nfs_page *);
61 : : size_t (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *,
62 : : struct nfs_page *);
63 : : int (*pg_doio)(struct nfs_pageio_descriptor *);
64 : : unsigned int (*pg_get_mirror_count)(struct nfs_pageio_descriptor *,
65 : : struct nfs_page *);
66 : : void (*pg_cleanup)(struct nfs_pageio_descriptor *);
67 : : };
68 : :
69 : : struct nfs_rw_ops {
70 : : struct nfs_pgio_header *(*rw_alloc_header)(void);
71 : : void (*rw_free_header)(struct nfs_pgio_header *);
72 : : int (*rw_done)(struct rpc_task *, struct nfs_pgio_header *,
73 : : struct inode *);
74 : : void (*rw_result)(struct rpc_task *, struct nfs_pgio_header *);
75 : : void (*rw_initiate)(struct nfs_pgio_header *, struct rpc_message *,
76 : : const struct nfs_rpc_ops *,
77 : : struct rpc_task_setup *, int);
78 : : };
79 : :
80 : : struct nfs_pgio_mirror {
81 : : struct list_head pg_list;
82 : : unsigned long pg_bytes_written;
83 : : size_t pg_count;
84 : : size_t pg_bsize;
85 : : unsigned int pg_base;
86 : : unsigned char pg_recoalesce : 1;
87 : : };
88 : :
89 : : struct nfs_pageio_descriptor {
90 : : struct inode *pg_inode;
91 : : const struct nfs_pageio_ops *pg_ops;
92 : : const struct nfs_rw_ops *pg_rw_ops;
93 : : int pg_ioflags;
94 : : int pg_error;
95 : : const struct rpc_call_ops *pg_rpc_callops;
96 : : const struct nfs_pgio_completion_ops *pg_completion_ops;
97 : : struct pnfs_layout_segment *pg_lseg;
98 : : struct nfs_io_completion *pg_io_completion;
99 : : struct nfs_direct_req *pg_dreq;
100 : : unsigned int pg_bsize; /* default bsize for mirrors */
101 : :
102 : : u32 pg_mirror_count;
103 : : struct nfs_pgio_mirror *pg_mirrors;
104 : : struct nfs_pgio_mirror pg_mirrors_static[1];
105 : : struct nfs_pgio_mirror *pg_mirrors_dynamic;
106 : : u32 pg_mirror_idx; /* current mirror */
107 : : unsigned short pg_maxretrans;
108 : : unsigned char pg_moreio : 1;
109 : : };
110 : :
111 : : /* arbitrarily selected limit to number of mirrors */
112 : : #define NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX 16
113 : :
114 : : #define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags))
115 : :
116 : : extern struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
117 : : struct page *page,
118 : : unsigned int offset,
119 : : unsigned int count);
120 : : extern void nfs_release_request(struct nfs_page *);
121 : :
122 : :
123 : : extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
124 : : struct inode *inode,
125 : : const struct nfs_pageio_ops *pg_ops,
126 : : const struct nfs_pgio_completion_ops *compl_ops,
127 : : const struct nfs_rw_ops *rw_ops,
128 : : size_t bsize,
129 : : int how);
130 : : extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
131 : : struct nfs_page *);
132 : : extern int nfs_pageio_resend(struct nfs_pageio_descriptor *,
133 : : struct nfs_pgio_header *);
134 : : extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
135 : : extern void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t);
136 : : extern size_t nfs_generic_pg_test(struct nfs_pageio_descriptor *desc,
137 : : struct nfs_page *prev,
138 : : struct nfs_page *req);
139 : : extern int nfs_wait_on_request(struct nfs_page *);
140 : : extern void nfs_unlock_request(struct nfs_page *req);
141 : : extern void nfs_unlock_and_release_request(struct nfs_page *);
142 : : extern int nfs_page_group_lock(struct nfs_page *);
143 : : extern void nfs_page_group_unlock(struct nfs_page *);
144 : : extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int);
145 : : extern bool nfs_async_iocounter_wait(struct rpc_task *, struct nfs_lock_context *);
146 : :
147 : : /*
148 : : * Lock the page of an asynchronous request
149 : : */
150 : : static inline int
151 : : nfs_lock_request(struct nfs_page *req)
152 : : {
153 : 0 : return !test_and_set_bit(PG_BUSY, &req->wb_flags);
154 : : }
155 : :
156 : : /**
157 : : * nfs_list_add_request - Insert a request into a list
158 : : * @req: request
159 : : * @head: head of list into which to insert the request.
160 : : */
161 : : static inline void
162 : : nfs_list_add_request(struct nfs_page *req, struct list_head *head)
163 : : {
164 : 0 : list_add_tail(&req->wb_list, head);
165 : : }
166 : :
167 : : /**
168 : : * nfs_list_move_request - Move a request to a new list
169 : : * @req: request
170 : : * @head: head of list into which to insert the request.
171 : : */
172 : : static inline void
173 : : nfs_list_move_request(struct nfs_page *req, struct list_head *head)
174 : : {
175 : 0 : list_move_tail(&req->wb_list, head);
176 : : }
177 : :
178 : : /**
179 : : * nfs_list_remove_request - Remove a request from its wb_list
180 : : * @req: request
181 : : */
182 : : static inline void
183 : : nfs_list_remove_request(struct nfs_page *req)
184 : : {
185 [ # # # # : 0 : if (list_empty(&req->wb_list))
# # # # #
# # # ]
186 : : return;
187 : : list_del_init(&req->wb_list);
188 : : }
189 : :
190 : : static inline struct nfs_page *
191 : : nfs_list_entry(struct list_head *head)
192 : : {
193 : : return list_entry(head, struct nfs_page, wb_list);
194 : : }
195 : :
196 : : static inline
197 : : loff_t req_offset(struct nfs_page *req)
198 : : {
199 : 0 : return (((loff_t)req->wb_index) << PAGE_SHIFT) + req->wb_offset;
200 : : }
201 : :
202 : : static inline struct nfs_open_context *
203 : : nfs_req_openctx(struct nfs_page *req)
204 : : {
205 : 0 : return req->wb_lock_context->open_context;
206 : : }
207 : :
208 : : #endif /* _LINUX_NFS_PAGE_H */
|