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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [ext/] [file.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/ext/file.c
3
 *
4
 *  Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
5
 *
6
 *  from
7
 *
8
 *  linux/fs/minix/file.c
9
 *
10
 *  Copyright (C) 1991, 1992 Linus Torvalds
11
 *
12
 *  ext regular file handling primitives
13
 */
14
 
15
#include <asm/segment.h>
16
#include <asm/system.h>
17
 
18
#include <linux/sched.h>
19
#include <linux/ext_fs.h>
20
#include <linux/kernel.h>
21
#include <linux/errno.h>
22
#include <linux/fcntl.h>
23
#include <linux/stat.h>
24
#include <linux/locks.h>
25
#include <linux/pagemap.h>
26
 
27
#define NBUF    32
28
 
29
#define MIN(a,b) (((a)<(b))?(a):(b))
30
#define MAX(a,b) (((a)>(b))?(a):(b))
31
 
32
#include <linux/fs.h>
33
#include <linux/ext_fs.h>
34
 
35
static int ext_file_read(struct inode *, struct file *, char *, int);
36
static int ext_file_write(struct inode *, struct file *, const char *, int);
37
 
38
/*
39
 * We have mostly NULL's here: the current defaults are ok for
40
 * the ext filesystem.
41
 */
42
static struct file_operations ext_file_operations = {
43
        NULL,                   /* lseek - default */
44
        ext_file_read,  /* read */
45
        ext_file_write, /* write */
46
        NULL,                   /* readdir - bad */
47
        NULL,                   /* select - default */
48
        NULL,                   /* ioctl - default */
49
        generic_file_mmap,      /* mmap */
50
        NULL,                   /* no special open is needed */
51
        NULL,                   /* release */
52
        ext_sync_file                   /* fsync */
53
};
54
 
55
struct inode_operations ext_file_inode_operations = {
56
        &ext_file_operations,   /* default file operations */
57
        NULL,                   /* create */
58
        NULL,                   /* lookup */
59
        NULL,                   /* link */
60
        NULL,                   /* unlink */
61
        NULL,                   /* symlink */
62
        NULL,                   /* mkdir */
63
        NULL,                   /* rmdir */
64
        NULL,                   /* mknod */
65
        NULL,                   /* rename */
66
        NULL,                   /* readlink */
67
        NULL,                   /* follow_link */
68
        generic_readpage,       /* readpage */
69
        NULL,                   /* writepage */
70
        ext_bmap,               /* bmap */
71
        ext_truncate,           /* truncate */
72
        NULL                    /* permission */
73
};
74
 
75
static int ext_file_read(struct inode * inode, struct file * filp, char * buf, int count)
76
{
77
        int read,left,chars;
78
        int block, blocks, offset;
79
        int bhrequest, uptodate;
80
        struct buffer_head ** bhb, ** bhe;
81
        struct buffer_head * bhreq[NBUF];
82
        struct buffer_head * buflist[NBUF];
83
        unsigned int size;
84
 
85
        if (!inode) {
86
                printk("ext_file_read: inode = NULL\n");
87
                return -EINVAL;
88
        }
89
        if (!S_ISREG(inode->i_mode)) {
90
                printk("ext_file_read: mode = %07o\n",inode->i_mode);
91
                return -EINVAL;
92
        }
93
        offset = filp->f_pos;
94
        size = inode->i_size;
95
        if (offset > size)
96
                left = 0;
97
        else
98
                left = size - offset;
99
        if (left > count)
100
                left = count;
101
        if (left <= 0)
102
                return 0;
103
        read = 0;
104
        block = offset >> BLOCK_SIZE_BITS;
105
        offset &= BLOCK_SIZE-1;
106
        size = (size + (BLOCK_SIZE-1)) >> BLOCK_SIZE_BITS;
107
        blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
108
        bhb = bhe = buflist;
109
        if (filp->f_reada) {
110
                if(blocks < read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9))
111
                  blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
112
                if (block + blocks > size)
113
                        blocks = size - block;
114
        }
115
 
116
        /* We do this in a two stage process.  We first try to request
117
           as many blocks as we can, then we wait for the first one to
118
           complete, and then we try to wrap up as many as are actually
119
           done.  This routine is rather generic, in that it can be used
120
           in a filesystem by substituting the appropriate function in
121
           for getblk.
122
 
123
           This routine is optimized to make maximum use of the various
124
           buffers and caches. */
125
 
126
        do {
127
                bhrequest = 0;
128
                uptodate = 1;
129
                while (blocks) {
130
                        --blocks;
131
                        *bhb = ext_getblk(inode, block++, 0);
132
                        if (*bhb && !buffer_uptodate(*bhb)) {
133
                                uptodate = 0;
134
                                bhreq[bhrequest++] = *bhb;
135
                        }
136
 
137
                        if (++bhb == &buflist[NBUF])
138
                                bhb = buflist;
139
 
140
                        /* If the block we have on hand is uptodate, go ahead
141
                           and complete processing. */
142
                        if (uptodate)
143
                                break;
144
                        if (bhb == bhe)
145
                                break;
146
                }
147
 
148
                /* Now request them all */
149
                if (bhrequest)
150
                        ll_rw_block(READ, bhrequest, bhreq);
151
 
152
                do { /* Finish off all I/O that has actually completed */
153
                        if (*bhe) {
154
                                wait_on_buffer(*bhe);
155
                                if (!buffer_uptodate(*bhe)) {   /* read error? */
156
                                        brelse(*bhe);
157
                                        if (++bhe == &buflist[NBUF])
158
                                          bhe = buflist;
159
                                        left = 0;
160
                                        break;
161
                                }
162
                        }
163
                        if (left < BLOCK_SIZE - offset)
164
                                chars = left;
165
                        else
166
                                chars = BLOCK_SIZE - offset;
167
                        filp->f_pos += chars;
168
                        left -= chars;
169
                        read += chars;
170
                        if (*bhe) {
171
                                memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
172
                                brelse(*bhe);
173
                                buf += chars;
174
                        } else {
175
                                while (chars-->0)
176
                                        put_user(0,buf++);
177
                        }
178
                        offset = 0;
179
                        if (++bhe == &buflist[NBUF])
180
                                bhe = buflist;
181
                } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
182
        } while (left > 0);
183
 
184
/* Release the read-ahead blocks */
185
        while (bhe != bhb) {
186
                brelse(*bhe);
187
                if (++bhe == &buflist[NBUF])
188
                        bhe = buflist;
189
        };
190
        if (!read)
191
                return -EIO;
192
        filp->f_reada = 1;
193
        if (!IS_RDONLY(inode)) {
194
                inode->i_atime = CURRENT_TIME;
195
                inode->i_dirt = 1;
196
        }
197
        return read;
198
}
199
 
200
static int ext_file_write(struct inode * inode, struct file * filp, const char * buf, int count)
201
{
202
        off_t pos;
203
        int written,c;
204
        struct buffer_head * bh;
205
        char * p;
206
 
207
        if (!inode) {
208
                printk("ext_file_write: inode = NULL\n");
209
                return -EINVAL;
210
        }
211
        if (!S_ISREG(inode->i_mode)) {
212
                printk("ext_file_write: mode = %07o\n",inode->i_mode);
213
                return -EINVAL;
214
        }
215
/*
216
 * ok, append may not work when many processes are writing at the same time
217
 * but so what. That way leads to madness anyway.
218
 */
219
        if (filp->f_flags & O_APPEND)
220
                pos = inode->i_size;
221
        else
222
                pos = filp->f_pos;
223
        written = 0;
224
        while (written<count) {
225
                bh = ext_getblk(inode,pos/BLOCK_SIZE,1);
226
                if (!bh) {
227
                        if (!written)
228
                                written = -ENOSPC;
229
                        break;
230
                }
231
                c = BLOCK_SIZE - (pos % BLOCK_SIZE);
232
                if (c > count-written)
233
                        c = count-written;
234
                if (c != BLOCK_SIZE && !buffer_uptodate(bh)) {
235
                        ll_rw_block(READ, 1, &bh);
236
                        wait_on_buffer(bh);
237
                        if (!buffer_uptodate(bh)) {
238
                                brelse(bh);
239
                                if (!written)
240
                                        written = -EIO;
241
                                break;
242
                        }
243
                }
244
                p = (pos % BLOCK_SIZE) + bh->b_data;
245
                memcpy_fromfs(p,buf,c);
246
                update_vm_cache(inode, pos, p, c);
247
                pos += c;
248
                if (pos > inode->i_size) {
249
                        inode->i_size = pos;
250
                        inode->i_dirt = 1;
251
                }
252
                written += c;
253
                buf += c;
254
                mark_buffer_uptodate(bh, 1);
255
                mark_buffer_dirty(bh, 0);
256
                brelse(bh);
257
        }
258
        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
259
        filp->f_pos = pos;
260
        inode->i_dirt = 1;
261
        return written;
262
}

powered by: WebSVN 2.1.0

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