6 * Partial copy of Linus' read cache modifications to fs/nfs/file.c
7 * modified for async RPC by okir@monad.swb.de
9 * We do an ugly hack here in order to return proper error codes to the
10 * user program when a read request failed: since generic_file_read
11 * only checks the return value of inode->i_op->readpage() which is always 0
12 * for async RPC, we set the error bit of the page to 1 when an error occurs,
13 * and make nfs_readpage transmit requests synchronously when encountering this.
14 * This is only a small problem, though, since we now retry all operations
15 * within the RPC code when root squashing is suspected.
18 #define NFS_NEED_XDR_TYPES
19 #include <linux/sched.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/fcntl.h>
23 #include <linux/stat.h>
25 #include <linux/malloc.h>
26 #include <linux/pagemap.h>
27 #include <linux/sunrpc/clnt.h>
28 #include <linux/nfs_fs.h>
30 #include <asm/segment.h>
31 #include <asm/system.h>
33 #define NFSDBG_FACILITY NFSDBG_PAGECACHE
36 struct inode
* ra_inode
; /* inode from which to read */
37 struct page
* ra_page
; /* page to be read */
38 struct nfs_readargs ra_args
; /* XDR argument struct */
39 struct nfs_readres ra_res
; /* ... and result struct */
40 struct nfs_fattr ra_fattr
; /* fattr storage */
43 /* Hack for future NFS swap support */
45 # define IS_SWAPFILE(inode) (0)
50 * Set up the NFS read request struct
53 nfs_readreq_setup(struct nfs_rreq
*req
, struct nfs_fh
*fh
,
54 unsigned long offset
, void *buffer
, unsigned int rsize
)
57 req
->ra_args
.offset
= offset
;
58 req
->ra_args
.count
= rsize
;
59 req
->ra_args
.buffer
= buffer
;
60 req
->ra_res
.fattr
= &req
->ra_fattr
;
61 req
->ra_res
.count
= rsize
;
66 * Read a page synchronously.
69 nfs_readpage_sync(struct dentry
*dentry
, struct inode
*inode
, struct page
*page
)
72 unsigned long offset
= page
->offset
;
73 char *buffer
= (char *) page_address(page
);
74 int rsize
= NFS_SERVER(inode
)->rsize
;
75 int result
, refresh
= 0;
76 int count
= PAGE_SIZE
;
77 int flags
= IS_SWAPFILE(inode
)? NFS_RPC_SWAPFLAGS
: 0;
79 dprintk("NFS: nfs_readpage_sync(%p)\n", page
);
80 clear_bit(PG_error
, &page
->flags
);
86 dprintk("NFS: nfs_proc_read(%s, (%s/%s), %ld, %d, %p)\n",
87 NFS_SERVER(inode
)->hostname
,
88 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
89 offset
, rsize
, buffer
);
91 /* Set up arguments and perform rpc call */
92 nfs_readreq_setup(&rqst
, NFS_FH(dentry
), offset
, buffer
, rsize
);
93 result
= rpc_call(NFS_CLIENT(inode
), NFSPROC_READ
,
94 &rqst
.ra_args
, &rqst
.ra_res
, flags
);
97 * Even if we had a partial success we can't mark the page
101 if (result
== -EISDIR
)
109 if (result
< rsize
) /* NFSv2ism */
113 memset(buffer
, 0, count
);
114 set_bit(PG_uptodate
, &page
->flags
);
118 /* Note: we don't refresh if the call returned error */
119 if (refresh
&& result
>= 0)
120 nfs_refresh_inode(inode
, &rqst
.ra_fattr
);
121 /* N.B. Use nfs_unlock_page here? */
122 clear_bit(PG_locked
, &page
->flags
);
123 wake_up(&page
->wait
);
128 * This is the callback from RPC telling us whether a reply was
129 * received or some error occurred (timeout or socket shutdown).
132 nfs_readpage_result(struct rpc_task
*task
)
134 struct nfs_rreq
*req
= (struct nfs_rreq
*) task
->tk_calldata
;
135 struct page
*page
= req
->ra_page
;
136 unsigned long address
= page_address(page
);
137 int result
= task
->tk_status
;
138 static int succ
= 0, fail
= 0;
140 dprintk("NFS: %4d received callback for page %lx, result %d\n",
141 task
->tk_pid
, address
, result
);
144 result
= req
->ra_res
.count
;
145 if (result
< PAGE_SIZE
) {
146 memset((char *) address
+ result
, 0, PAGE_SIZE
- result
);
148 nfs_refresh_inode(req
->ra_inode
, &req
->ra_fattr
);
149 set_bit(PG_uptodate
, &page
->flags
);
152 set_bit(PG_error
, &page
->flags
);
154 dprintk("NFS: %d successful reads, %d failures\n", succ
, fail
);
156 /* N.B. Use nfs_unlock_page here? */
157 clear_bit(PG_locked
, &page
->flags
);
158 wake_up(&page
->wait
);
162 rpc_release_task(task
);
167 nfs_readpage_async(struct dentry
*dentry
, struct inode
*inode
,
170 unsigned long address
= page_address(page
);
171 struct nfs_rreq
*req
;
172 int result
= -1, flags
;
174 dprintk("NFS: nfs_readpage_async(%p)\n", page
);
175 if (NFS_CONGESTED(inode
))
178 /* N.B. Do we need to test? Never called for swapfile inode */
179 flags
= RPC_TASK_ASYNC
| (IS_SWAPFILE(inode
)? NFS_RPC_SWAPFLAGS
: 0);
180 req
= (struct nfs_rreq
*) rpc_allocate(flags
, sizeof(*req
));
184 /* Initialize request */
185 /* N.B. Will the dentry remain valid for life of request? */
186 nfs_readreq_setup(req
, NFS_FH(dentry
), page
->offset
,
187 (void *) address
, PAGE_SIZE
);
188 req
->ra_inode
= inode
;
189 req
->ra_page
= page
; /* count has been incremented by caller */
191 /* Start the async call */
192 dprintk("NFS: executing async READ request.\n");
193 result
= rpc_do_call(NFS_CLIENT(inode
), NFSPROC_READ
,
194 &req
->ra_args
, &req
->ra_res
, flags
,
195 nfs_readpage_result
, req
);
203 dprintk("NFS: deferring async READ request.\n");
206 dprintk("NFS: failed to enqueue async READ request.\n");
212 * Read a page over NFS.
213 * We read the page synchronously in the following cases:
214 * - The file is a swap file. Swap-ins are always sync operations,
215 * so there's no need bothering to make async reads 100% fail-safe.
216 * - The NFS rsize is smaller than PAGE_SIZE. We could kludge our way
217 * around this by creating several consecutive read requests, but
218 * that's hardly worth it.
219 * - The error flag is set for this page. This happens only when a
220 * previous async read operation failed.
221 * - The server is congested.
224 nfs_readpage(struct file
*file
, struct page
*page
)
226 struct dentry
*dentry
= file
->f_dentry
;
227 struct inode
*inode
= dentry
->d_inode
;
230 dprintk("NFS: nfs_readpage (%p %ld@%ld)\n",
231 page
, PAGE_SIZE
, page
->offset
);
232 set_bit(PG_locked
, &page
->flags
);
233 atomic_inc(&page
->count
);
234 if (!IS_SWAPFILE(inode
) && !PageError(page
) &&
235 NFS_SERVER(inode
)->rsize
>= PAGE_SIZE
)
236 error
= nfs_readpage_async(dentry
, inode
, page
);
237 if (error
< 0) { /* couldn't enqueue */
238 error
= nfs_readpage_sync(dentry
, inode
, page
);
239 if (error
< 0 && IS_SWAPFILE(inode
))
240 printk("Aiee.. nfs swap-in of page failed!\n");
241 free_page(page_address(page
));