|
1 /* |
|
2 * linux/include/linux/nfs_page.h |
|
3 * |
|
4 * Copyright (C) 2000 Trond Myklebust |
|
5 * |
|
6 * NFS page cache wrapper. |
|
7 */ |
|
8 |
|
9 #ifndef _LINUX_NFS_PAGE_H |
|
10 #define _LINUX_NFS_PAGE_H |
|
11 |
|
12 |
|
13 #include <linux/list.h> |
|
14 #include <linux/pagemap.h> |
|
15 #include <linux/wait.h> |
|
16 #include <linux/sunrpc/auth.h> |
|
17 #include <linux/nfs_xdr.h> |
|
18 |
|
19 #include <linux/kref.h> |
|
20 |
|
21 /* |
|
22 * Valid flags for the radix tree |
|
23 */ |
|
24 #define NFS_PAGE_TAG_LOCKED 0 |
|
25 #define NFS_PAGE_TAG_COMMIT 1 |
|
26 |
|
27 /* |
|
28 * Valid flags for a dirty buffer |
|
29 */ |
|
30 enum { |
|
31 PG_BUSY = 0, |
|
32 PG_CLEAN, |
|
33 PG_NEED_COMMIT, |
|
34 PG_NEED_RESCHED, |
|
35 }; |
|
36 |
|
37 struct nfs_inode; |
|
38 struct nfs_page { |
|
39 struct list_head wb_list; /* Defines state of page: */ |
|
40 struct page *wb_page; /* page to read in/write out */ |
|
41 struct nfs_open_context *wb_context; /* File state context info */ |
|
42 atomic_t wb_complete; /* i/os we're waiting for */ |
|
43 pgoff_t wb_index; /* Offset >> PAGE_CACHE_SHIFT */ |
|
44 unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */ |
|
45 wb_pgbase, /* Start of page data */ |
|
46 wb_bytes; /* Length of request */ |
|
47 struct kref wb_kref; /* reference count */ |
|
48 unsigned long wb_flags; |
|
49 struct nfs_writeverf wb_verf; /* Commit cookie */ |
|
50 }; |
|
51 |
|
52 struct nfs_pageio_descriptor { |
|
53 struct list_head pg_list; |
|
54 unsigned long pg_bytes_written; |
|
55 size_t pg_count; |
|
56 size_t pg_bsize; |
|
57 unsigned int pg_base; |
|
58 |
|
59 struct inode *pg_inode; |
|
60 int (*pg_doio)(struct inode *, struct list_head *, unsigned int, size_t, int); |
|
61 int pg_ioflags; |
|
62 int pg_error; |
|
63 }; |
|
64 |
|
65 #define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags)) |
|
66 |
|
67 extern struct nfs_page *nfs_create_request(struct nfs_open_context *ctx, |
|
68 struct inode *inode, |
|
69 struct page *page, |
|
70 unsigned int offset, |
|
71 unsigned int count); |
|
72 extern void nfs_clear_request(struct nfs_page *req); |
|
73 extern void nfs_release_request(struct nfs_page *req); |
|
74 |
|
75 |
|
76 extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst, |
|
77 pgoff_t idx_start, unsigned int npages, int tag); |
|
78 extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc, |
|
79 struct inode *inode, |
|
80 int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int), |
|
81 size_t bsize, |
|
82 int how); |
|
83 extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *, |
|
84 struct nfs_page *); |
|
85 extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc); |
|
86 extern void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t); |
|
87 extern int nfs_wait_on_request(struct nfs_page *); |
|
88 extern void nfs_unlock_request(struct nfs_page *req); |
|
89 extern int nfs_set_page_tag_locked(struct nfs_page *req); |
|
90 extern void nfs_clear_page_tag_locked(struct nfs_page *req); |
|
91 |
|
92 |
|
93 /* |
|
94 * Lock the page of an asynchronous request without getting a new reference |
|
95 */ |
|
96 static inline int |
|
97 nfs_lock_request_dontget(struct nfs_page *req) |
|
98 { |
|
99 return !test_and_set_bit(PG_BUSY, &req->wb_flags); |
|
100 } |
|
101 |
|
102 /** |
|
103 * nfs_list_add_request - Insert a request into a list |
|
104 * @req: request |
|
105 * @head: head of list into which to insert the request. |
|
106 */ |
|
107 static inline void |
|
108 nfs_list_add_request(struct nfs_page *req, struct list_head *head) |
|
109 { |
|
110 list_add_tail(&req->wb_list, head); |
|
111 } |
|
112 |
|
113 |
|
114 /** |
|
115 * nfs_list_remove_request - Remove a request from its wb_list |
|
116 * @req: request |
|
117 */ |
|
118 static inline void |
|
119 nfs_list_remove_request(struct nfs_page *req) |
|
120 { |
|
121 if (list_empty(&req->wb_list)) |
|
122 return; |
|
123 list_del_init(&req->wb_list); |
|
124 } |
|
125 |
|
126 static inline struct nfs_page * |
|
127 nfs_list_entry(struct list_head *head) |
|
128 { |
|
129 return list_entry(head, struct nfs_page, wb_list); |
|
130 } |
|
131 |
|
132 static inline |
|
133 loff_t req_offset(struct nfs_page *req) |
|
134 { |
|
135 return (((loff_t)req->wb_index) << PAGE_CACHE_SHIFT) + req->wb_offset; |
|
136 } |
|
137 |
|
138 #endif /* _LINUX_NFS_PAGE_H */ |