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>
29 #include <linux/smp_lock.h>
31 #include <asm/segment.h>
32 #include <asm/system.h>
34 #define NFSDBG_FACILITY NFSDBG_PAGECACHE
37 struct inode
* ra_inode
; /* inode from which to read */
38 struct page
* ra_page
; /* page to be read */
39 struct nfs_readargs ra_args
; /* XDR argument struct */
40 struct nfs_readres ra_res
; /* ... and result struct */
41 struct nfs_fattr ra_fattr
; /* fattr storage */
44 /* Hack for future NFS swap support */
46 # define IS_SWAPFILE(inode) (0)
51 * Set up the NFS read request struct
54 nfs_readreq_setup(struct nfs_rreq
*req
, struct nfs_fh
*fh
,
55 unsigned long offset
, void *buffer
, unsigned int rsize
)
58 req
->ra_args
.offset
= offset
;
59 req
->ra_args
.count
= rsize
;
60 req
->ra_args
.buffer
= buffer
;
61 req
->ra_res
.fattr
= &req
->ra_fattr
;
62 req
->ra_res
.count
= rsize
;
67 * Read a page synchronously.
70 nfs_readpage_sync(struct dentry
*dentry
, struct inode
*inode
, struct page
*page
)
73 unsigned long offset
= page
->index
<< PAGE_CACHE_SHIFT
;
75 int rsize
= NFS_SERVER(inode
)->rsize
;
76 int result
, refresh
= 0;
77 int count
= PAGE_SIZE
;
78 int flags
= IS_SWAPFILE(inode
)? NFS_RPC_SWAPFLAGS
: 0;
80 dprintk("NFS: nfs_readpage_sync(%p)\n", page
);
83 * This works now because the socket layer never tries to DMA
84 * into this buffer directly.
86 buffer
= (char *) kmap(page
);
92 dprintk("NFS: nfs_proc_read(%s, (%s/%s), %ld, %d, %p)\n",
93 NFS_SERVER(inode
)->hostname
,
94 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
95 offset
, rsize
, buffer
);
97 /* Set up arguments and perform rpc call */
98 nfs_readreq_setup(&rqst
, NFS_FH(dentry
), offset
, buffer
, rsize
);
100 result
= rpc_call(NFS_CLIENT(inode
), NFSPROC_READ
, &rqst
.ra_args
, &rqst
.ra_res
, flags
);
104 * Even if we had a partial success we can't mark the page
108 if (result
== -EISDIR
)
116 if (result
< rsize
) /* NFSv2ism */
120 memset(buffer
, 0, count
);
121 SetPageUptodate(page
);
127 /* Note: we don't refresh if the call returned error */
128 if (refresh
&& result
>= 0)
129 nfs_refresh_inode(inode
, &rqst
.ra_fattr
);
134 * This is the callback from RPC telling us whether a reply was
135 * received or some error occurred (timeout or socket shutdown).
138 nfs_readpage_result(struct rpc_task
*task
)
140 struct nfs_rreq
*req
= (struct nfs_rreq
*) task
->tk_calldata
;
141 struct page
*page
= req
->ra_page
;
142 unsigned long address
= page_address(page
);
143 int result
= task
->tk_status
;
144 static int succ
= 0, fail
= 0;
146 dprintk("NFS: %4d received callback for page %lx, result %d\n",
147 task
->tk_pid
, address
, result
);
150 result
= req
->ra_res
.count
;
151 if (result
< PAGE_SIZE
) {
152 memset((char *) address
+ result
, 0, PAGE_SIZE
- result
);
154 nfs_refresh_inode(req
->ra_inode
, &req
->ra_fattr
);
155 SetPageUptodate(page
);
160 dprintk("NFS: %d successful reads, %d failures\n", succ
, fail
);
166 rpc_release_task(task
);
171 nfs_readpage_async(struct dentry
*dentry
, struct inode
*inode
,
174 unsigned long address
;
175 struct nfs_rreq
*req
;
176 int result
= -1, flags
;
178 dprintk("NFS: nfs_readpage_async(%p)\n", page
);
179 if (NFS_CONGESTED(inode
))
182 /* N.B. Do we need to test? Never called for swapfile inode */
183 flags
= RPC_TASK_ASYNC
| (IS_SWAPFILE(inode
)? NFS_RPC_SWAPFLAGS
: 0);
184 req
= (struct nfs_rreq
*) rpc_allocate(flags
, sizeof(*req
));
188 address
= kmap(page
);
189 /* Initialize request */
190 /* N.B. Will the dentry remain valid for life of request? */
191 nfs_readreq_setup(req
, NFS_FH(dentry
), page
->index
<< PAGE_CACHE_SHIFT
,
192 (void *) address
, PAGE_SIZE
);
193 req
->ra_inode
= inode
;
194 req
->ra_page
= page
; /* count has been incremented by caller */
196 /* Start the async call */
197 dprintk("NFS: executing async READ request.\n");
198 result
= rpc_do_call(NFS_CLIENT(inode
), NFSPROC_READ
,
199 &req
->ra_args
, &req
->ra_res
, flags
,
200 nfs_readpage_result
, req
);
208 dprintk("NFS: deferring async READ request.\n");
211 dprintk("NFS: failed to enqueue async READ request.\n");
218 * Read a page over NFS.
219 * We read the page synchronously in the following cases:
220 * - The file is a swap file. Swap-ins are always sync operations,
221 * so there's no need bothering to make async reads 100% fail-safe.
222 * - The NFS rsize is smaller than PAGE_SIZE. We could kludge our way
223 * around this by creating several consecutive read requests, but
224 * that's hardly worth it.
225 * - The error flag is set for this page. This happens only when a
226 * previous async read operation failed.
227 * - The server is congested.
230 nfs_readpage(struct dentry
*dentry
, struct page
*page
)
232 struct inode
*inode
= dentry
->d_inode
;
236 dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
237 page
, PAGE_SIZE
, page
->index
);
241 * Try to flush any pending writes to the file..
243 * NOTE! Because we own the page lock, there cannot
244 * be any new pending writes generated at this point
245 * for this page (other pages can be written to).
247 error
= nfs_wb_page(inode
, page
);
252 if (!IS_SWAPFILE(inode
) && !PageError(page
) &&
253 NFS_SERVER(inode
)->rsize
>= PAGE_SIZE
)
254 error
= nfs_readpage_async(dentry
, inode
, page
);
258 error
= nfs_readpage_sync(dentry
, inode
, page
);
259 if (error
< 0 && IS_SWAPFILE(inode
))
260 printk("Aiee.. nfs swap-in of page failed!\n");