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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [block_dev.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1627 jcastillo
/*
2
 *  linux/fs/block_dev.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
 
7
#include <linux/errno.h>
8
#include <linux/sched.h>
9
#include <linux/kernel.h>
10
#include <linux/locks.h>
11
#include <linux/fcntl.h>
12
#include <linux/mm.h>
13
 
14
#include <asm/segment.h>
15
#include <asm/system.h>
16
 
17
extern int *blk_size[];
18
extern int *blksize_size[];
19
 
20
#define MAX_BUF_PER_PAGE (PAGE_SIZE / 512)
21
#define NBUF 64
22
 
23
int block_write(struct inode * inode, struct file * filp,
24
        const char * buf, int count)
25
{
26
        int blocksize, blocksize_bits, i, buffercount,write_error;
27
        int block, blocks;
28
        loff_t offset;
29
        int chars;
30
        int written = 0;
31
        struct buffer_head * bhlist[NBUF];
32
        unsigned int size;
33
        kdev_t dev;
34
        struct buffer_head * bh, *bufferlist[NBUF];
35
        register char * p;
36
 
37
        write_error = buffercount = 0;
38
        dev = inode->i_rdev;
39
        if ( is_read_only( inode->i_rdev ))
40
                return -EPERM;
41
        blocksize = BLOCK_SIZE;
42
        if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
43
                blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
44
 
45
 
46
        i = blocksize;
47
        blocksize_bits = 0;
48
        while(i != 1) {
49
                blocksize_bits++;
50
                i >>= 1;
51
        }
52
 
53
        block = filp->f_pos >> blocksize_bits;
54
        offset = (loff_t)filp->f_pos & (blocksize-1);
55
 
56
        if (blk_size[MAJOR(dev)])
57
                size = ((loff_t) blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS) >> blocksize_bits;
58
        else
59
                size = INT_MAX;
60
        while (count>0) {
61
 
62
                if (block >= size)
63
                        return written ? written : -ENOSPC;
64
 
65
                chars = blocksize - offset;
66
                if (chars > count)
67
                        chars=count;
68
 
69
#if 0
70
                /* get the buffer head */
71
                {
72
                        struct buffer_head * (*fn)(kdev_t, int, int) = getblk;
73
                        if (chars != blocksize)
74
                                fn = bread;
75
                        bh = fn(dev, block, blocksize);
76
                }
77
#else
78
                bh = getblk(dev, block, blocksize);
79
 
80
                if (chars != blocksize && !buffer_uptodate(bh)) {
81
                  if(!filp->f_reada ||
82
                     !read_ahead[MAJOR(dev)]) {
83
                    /* We do this to force the read of a single buffer */
84
                    brelse(bh);
85
                    bh = bread(dev,block,blocksize);
86
                  } else {
87
                    /* Read-ahead before write */
88
                    blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9) / 2;
89
                    if (block + blocks > size) blocks = size - block;
90
                    if (blocks > NBUF) blocks=NBUF;
91
                    bhlist[0] = bh;
92
                    for(i=1; i<blocks; i++){
93
                      bhlist[i] = getblk (dev, block+i, blocksize);
94
                      if(!bhlist[i]){
95
                        while(i >= 0) brelse(bhlist[i--]);
96
                        return written ? written : -EIO;
97
                      };
98
                    };
99
                    ll_rw_block(READ, blocks, bhlist);
100
                    for(i=1; i<blocks; i++) brelse(bhlist[i]);
101
                    wait_on_buffer(bh);
102
 
103
                  };
104
                };
105
#endif
106
                block++;
107
                if (!bh)
108
                        return written ? written : -EIO;
109
                p = offset + bh->b_data;
110
                offset = 0;
111
                filp->f_pos += chars;
112
                written += chars;
113
                count -= chars;
114
                memcpy_fromfs(p,buf,chars);
115
                p += chars;
116
                buf += chars;
117
                mark_buffer_uptodate(bh, 1);
118
                mark_buffer_dirty(bh, 0);
119
                if (filp->f_flags & O_SYNC)
120
                        bufferlist[buffercount++] = bh;
121
                else
122
                        brelse(bh);
123
                if (buffercount == NBUF){
124
                        ll_rw_block(WRITE, buffercount, bufferlist);
125
                        for(i=0; i<buffercount; i++){
126
                                wait_on_buffer(bufferlist[i]);
127
                                if (!buffer_uptodate(bufferlist[i]))
128
                                        write_error=1;
129
                                brelse(bufferlist[i]);
130
                        }
131
                        buffercount=0;
132
                }
133
                if(write_error)
134
                        break;
135
        }
136
        if ( buffercount ){
137
                ll_rw_block(WRITE, buffercount, bufferlist);
138
                for(i=0; i<buffercount; i++){
139
                        wait_on_buffer(bufferlist[i]);
140
                        if (!buffer_uptodate(bufferlist[i]))
141
                                write_error=1;
142
                        brelse(bufferlist[i]);
143
                }
144
        }
145
        filp->f_reada = 1;
146
        if(write_error)
147
                return -EIO;
148
        return written;
149
}
150
 
151
int block_read(struct inode * inode, struct file * filp,
152
        char * buf, int count)
153
{
154
        unsigned int block;
155
        loff_t offset;
156
        int blocksize;
157
        int blocksize_bits, i;
158
        unsigned int blocks, rblocks, left;
159
        int bhrequest, uptodate;
160
        struct buffer_head ** bhb, ** bhe;
161
        struct buffer_head * buflist[NBUF];
162
        struct buffer_head * bhreq[NBUF];
163
        unsigned int chars;
164
        loff_t size;
165
        kdev_t dev;
166
        int read;
167
        extern struct file_operations * get_blkfops(unsigned int);
168
 
169
        dev = inode->i_rdev;
170
        blocksize = BLOCK_SIZE;
171
        if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
172
                blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
173
        i = blocksize;
174
        blocksize_bits = 0;
175
        while (i != 1) {
176
                blocksize_bits++;
177
                i >>= 1;
178
        }
179
 
180
        offset = filp->f_pos;
181
        if (blk_size[MAJOR(dev)])
182
                size = (loff_t) blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
183
        else
184
                size = INT_MAX;
185
 
186
        if (offset > size)
187
                left = 0;
188
        /* size - offset might not fit into left, so check explicitly. */
189
        else if (size - offset > INT_MAX)
190
                left = INT_MAX;
191
        else
192
                left = size - offset;
193
        if (left > count)
194
                left = count;
195
        if (left <= 0)
196
                return 0;
197
 
198
#ifdef MAGIC_ROM_PTR
199
        /* Logic: if romptr f_op is available on device, attempt to locate a
200
         * pointer into ROM for the desired data. If available, copy the data
201
         * directly to the caller's buffer. If any of this fails, proceed
202
         * with traditional approach of invoking block device.
203
         *
204
         * Note that this path only requires that the pointer (and the data
205
         * it points to) to be valid until the memcpy_tofs is complete.
206
         *
207
         *      -- Kenneth Albanowski
208
         */
209
 
210
        if (get_blkfops(MAJOR(dev))->romptr) {
211
                struct vm_area_struct vma;
212
                vma.vm_start = 0;
213
                vma.vm_offset = offset;
214
                if (!get_blkfops(MAJOR(dev))->romptr(inode, filp, &vma)) {
215
                        memcpy_tofs(buf, (void*)vma.vm_start, left);
216
                        filp->f_pos += count;
217
                        return count;
218
                }
219
        }
220
#endif /* MAGIC_ROM_PTR */
221
 
222
        read = 0;
223
        block = offset >> blocksize_bits;
224
        offset &= blocksize-1;
225
        size >>= blocksize_bits;
226
        rblocks = blocks = (left + offset + blocksize - 1) >> blocksize_bits;
227
        bhb = bhe = buflist;
228
        if (filp->f_reada) {
229
                if (blocks < read_ahead[MAJOR(dev)] / (blocksize >> 9))
230
                        blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9);
231
                if (rblocks > blocks)
232
                        blocks = rblocks;
233
 
234
        }
235
        if (block + blocks > size) {
236
                blocks = size - block;
237
                if (blocks == 0)
238
                        return 0;
239
        }
240
 
241
        /* We do this in a two stage process.  We first try to request
242
           as many blocks as we can, then we wait for the first one to
243
           complete, and then we try to wrap up as many as are actually
244
           done.  This routine is rather generic, in that it can be used
245
           in a filesystem by substituting the appropriate function in
246
           for getblk.
247
 
248
           This routine is optimized to make maximum use of the various
249
           buffers and caches. */
250
 
251
        do {
252
                bhrequest = 0;
253
                uptodate = 1;
254
                while (blocks) {
255
                        --blocks;
256
                        *bhb = getblk(dev, block++, blocksize);
257
                        if (*bhb && !buffer_uptodate(*bhb)) {
258
                                uptodate = 0;
259
                                bhreq[bhrequest++] = *bhb;
260
                        }
261
 
262
                        if (++bhb == &buflist[NBUF])
263
                                bhb = buflist;
264
 
265
                        /* If the block we have on hand is uptodate, go ahead
266
                           and complete processing. */
267
                        if (uptodate)
268
                                break;
269
                        if (bhb == bhe)
270
                                break;
271
                }
272
 
273
                /* Now request them all */
274
                if (bhrequest) {
275
                        ll_rw_block(READ, bhrequest, bhreq);
276
                }
277
 
278
                do { /* Finish off all I/O that has actually completed */
279
                        if (*bhe) {
280
                                wait_on_buffer(*bhe);
281
                                if (!buffer_uptodate(*bhe)) {   /* read error? */
282
                                        brelse(*bhe);
283
                                        if (++bhe == &buflist[NBUF])
284
                                          bhe = buflist;
285
                                        left = 0;
286
                                        break;
287
                                }
288
                        }
289
                        if (left < blocksize - offset)
290
                                chars = left;
291
                        else
292
                                chars = blocksize - offset;
293
                        filp->f_pos += chars;
294
                        left -= chars;
295
                        read += chars;
296
                        if (*bhe) {
297
                                memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
298
                                brelse(*bhe);
299
                                buf += chars;
300
                        } else {
301
                                while (chars-- > 0)
302
                                        put_user(0,buf++);
303
                        }
304
                        offset = 0;
305
                        if (++bhe == &buflist[NBUF])
306
                                bhe = buflist;
307
                } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
308
        } while (left > 0);
309
 
310
/* Release the read-ahead blocks */
311
        while (bhe != bhb) {
312
                brelse(*bhe);
313
                if (++bhe == &buflist[NBUF])
314
                        bhe = buflist;
315
        };
316
        if (!read)
317
                return -EIO;
318
        filp->f_reada = 1;
319
        return read;
320
}
321
 
322
void invalidate_buffers_by_byte(kdev_t dev, unsigned long pos, unsigned long len)
323
{
324
        int blocksize;
325
        int startblock, endblock;
326
 
327
        blocksize = BLOCK_SIZE;
328
        if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
329
                blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
330
 
331
        startblock = pos / blocksize;
332
        endblock = (pos+len-1) / blocksize;
333
 
334
        invalidate_buffers_by_block(dev, startblock, endblock-startblock+1);
335
 
336
}
337
 
338
 
339
int block_fsync(struct inode *inode, struct file *filp)
340
{
341
        return fsync_dev (inode->i_rdev);
342
}
343
 

powered by: WebSVN 2.1.0

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