OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [nfs/] [bio.c] - Blame information for rev 1628

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 * linux/fs/nfs/bio.c
3
 *
4
 * Block I/O for NFS
5
 *
6
 * Partial copy of Linus' read cache modifications to fs/nfs/file.c
7
 * modified for async RPC by okir@monad.swb.de
8
 *
9
 * We do an ugly hack here in order to return proper error codes to the
10
 * user program when a read request failed. This is a huge problem because
11
 * generic_file_read only checks the return value of inode->i_op->readpage()
12
 * which is usually 0 for async RPC. To overcome this obstacle, we set
13
 * the error bit of the page to 1 when an error occurs, and make nfs_readpage
14
 * transmit requests synchronously when encountering this.
15
 *
16
 * Another possible solution to this problem may be to have a cache of recent
17
 * RPC call results indexed by page pointer, or even a result code field
18
 * in struct page.
19
 *
20
 * June 96: Added retries of RPCs that seem to have failed for a transient
21
 * reason.
22
 */
23
 
24
#include <linux/sched.h>
25
#include <linux/kernel.h>
26
#include <linux/errno.h>
27
#include <linux/fcntl.h>
28
#include <linux/stat.h>
29
#include <linux/mm.h>
30
#include <linux/nfs_fs.h>
31
#include <linux/nfsiod.h>
32
#include <linux/malloc.h>
33
#include <linux/pagemap.h>
34
 
35
#include <asm/segment.h>
36
#include <asm/system.h>
37
 
38
#undef DEBUG_BIO
39
#ifdef DEBUG_BIO
40
#define dprintk(args...)        printk(## args)
41
#else
42
#define dprintk(args...)        /* nothing */
43
#endif
44
 
45
static inline int
46
do_read_nfs_sync(struct inode * inode, struct page * page)
47
{
48
        struct nfs_fattr fattr;
49
        int             result, refresh = 0;
50
        int             count = PAGE_SIZE;
51
        int             rsize = NFS_SERVER(inode)->rsize;
52
        char            *buf = (char *) page_address(page);
53
        unsigned long   pos = page->offset;
54
 
55
        dprintk("NFS: do_read_nfs_sync(%p)\n", page);
56
 
57
        set_bit(PG_locked, &page->flags);
58
        clear_bit(PG_error, &page->flags);
59
 
60
        do {
61
                if (count < rsize)
62
                        rsize = count;
63
                result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
64
                        pos, rsize, buf, &fattr);
65
                dprintk("nfs_proc_read(%s, (%x,%lx), %ld, %d, %p) = %d\n",
66
                                NFS_SERVER(inode)->hostname,
67
                                inode->i_dev, inode->i_ino,
68
                                pos, rsize, buf, result);
69
                /*
70
                 * Even if we had a partial success we can't mark the page
71
                 * cache valid.
72
                 */
73
                if (result < 0)
74
                        goto io_error;
75
                refresh = 1;
76
                count -= result;
77
                pos += result;
78
                buf += result;
79
                if (result < rsize)
80
                        break;
81
        } while (count);
82
 
83
        memset(buf, 0, count);
84
        set_bit(PG_uptodate, &page->flags);
85
        result = 0;
86
 
87
io_error:
88
        if (refresh)
89
                nfs_refresh_inode(inode, &fattr);
90
        clear_bit(PG_locked, &page->flags);
91
        wake_up(&page->wait);
92
        return result;
93
}
94
 
95
/*
96
 * This is the function to (re-) transmit an NFS readahead request
97
 */
98
static int
99
nfsiod_read_setup(struct nfsiod_req *req)
100
{
101
        struct inode    *inode = req->rq_inode;
102
        struct page     *page = req->rq_page;
103
 
104
        return nfs_proc_read_request(&req->rq_rpcreq,
105
                        NFS_SERVER(inode), NFS_FH(inode),
106
                        page->offset, PAGE_SIZE,
107
                        (__u32 *) page_address(page));
108
}
109
 
110
/*
111
 * This is the callback from nfsiod telling us whether a reply was
112
 * received or some error occurred (timeout or socket shutdown).
113
 */
114
static int
115
nfsiod_read_result(int result, struct nfsiod_req *req)
116
{
117
        struct nfs_server *server = NFS_SERVER(req->rq_inode);
118
        struct page     *page = req->rq_page;
119
        static int      succ = 0, fail = 0;
120
        int             i;
121
 
122
        dprintk("BIO: received callback for page %p, result %d\n",
123
                        page, result);
124
 
125
        if (result >= 0) {
126
                struct nfs_fattr        fattr;
127
 
128
                result = nfs_proc_read_reply(&req->rq_rpcreq, &fattr);
129
                if (result >= 0) {
130
                        nfs_refresh_inode(req->rq_inode, &fattr);
131
                        if (result < PAGE_SIZE)
132
                                memset((u8 *) page_address(page)+result,
133
                                                0, PAGE_SIZE-result);
134
                }
135
        } else
136
        if (result == -ETIMEDOUT && !(server->flags & NFS_MOUNT_SOFT)) {
137
                /* XXX: Theoretically, we'd have to increment the initial
138
                 * timeo here; but I'm not going to bother with this now
139
                 * because this old nfsiod stuff will soon die anyway.
140
                 */
141
                result = -EAGAIN;
142
        }
143
 
144
        if (result == -EAGAIN && req->rq_retries--) {
145
                dprintk("BIO: retransmitting request.\n");
146
                memset(&req->rq_rpcreq, 0, sizeof(struct rpc_ioreq));
147
                while (rpc_reserve(server->rsock, &req->rq_rpcreq, 1) < 0)
148
                        schedule();
149
                current->fsuid = req->rq_fsuid;
150
                current->fsgid = req->rq_fsgid;
151
                for (i = 0; i < NGROUPS; i++)
152
                        current->groups[i] = req->rq_groups[i];
153
                nfsiod_read_setup(req);
154
                return 0;
155
        }
156
        if (result >= 0) {
157
                set_bit(PG_uptodate, &page->flags);
158
                succ++;
159
        } else {
160
                dprintk("BIO: %d successful reads, %d failures\n", succ, fail);
161
                set_bit(PG_error, &page->flags);
162
                fail++;
163
        }
164
        clear_bit(PG_locked, &page->flags);
165
        wake_up(&page->wait);
166
        free_page(page_address(page));
167
        return 1;
168
}
169
 
170
static inline int
171
do_read_nfs_async(struct inode *inode, struct page *page)
172
{
173
        struct nfsiod_req *req;
174
        int             result, i;
175
 
176
        dprintk("NFS: do_read_nfs_async(%p)\n", page);
177
 
178
        set_bit(PG_locked, &page->flags);
179
        clear_bit(PG_error, &page->flags);
180
 
181
        if (!(req = nfsiod_reserve(NFS_SERVER(inode))))
182
                return -EAGAIN;
183
 
184
        req->rq_retries = 5;
185
        req->rq_callback = nfsiod_read_result;
186
        req->rq_inode = inode;
187
        req->rq_page = page;
188
 
189
        req->rq_fsuid = current->fsuid;
190
        req->rq_fsgid = current->fsgid;
191
        for (i = 0; i < NGROUPS; i++)
192
                req->rq_groups[i] = current->groups[i];
193
 
194
        if ((result = nfsiod_read_setup(req)) >= 0) {
195
                page->count++;
196
                nfsiod_enqueue(req);
197
        } else {
198
                dprintk("NFS: deferring async READ request.\n");
199
                nfsiod_release(req);
200
                clear_bit(PG_locked, &page->flags);
201
                wake_up(&page->wait);
202
        }
203
 
204
        return result < 0? result : 0;
205
}
206
 
207
int
208
nfs_readpage(struct inode *inode, struct page *page)
209
{
210
        unsigned long   address;
211
        int             error = -1;
212
 
213
        /* In case we're called from a page fault we want to */
214
        /* make sure we're runnable before we schedule.. */
215
        current->state = TASK_RUNNING;
216
        dprintk("NFS: nfs_readpage %08lx\n", page_address(page));
217
        address = page_address(page);
218
        page->count++;
219
        if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_SIZE)
220
                error = do_read_nfs_async(inode, page);
221
        if (error < 0)           /* couldn't enqueue */
222
                error = do_read_nfs_sync(inode, page);
223
        free_page(address);
224
        return error;
225
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.