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

Subversion Repositories or1k

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

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

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

powered by: WebSVN 2.1.0

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