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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [efs/] [inode.c] - Blame information for rev 1275

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

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * inode.c
3
 *
4
 * Copyright (c) 1999 Al Smith
5
 *
6
 * Portions derived from work (c) 1995,1996 Christian Vogelgsang,
7
 *              and from work (c) 1998 Mike Shaver.
8
 */
9
 
10
#include <linux/efs_fs.h>
11
#include <linux/efs_fs_sb.h>
12
#include <linux/module.h>
13
 
14
 
15
extern int efs_get_block(struct inode *, long, struct buffer_head *, int);
16
static int efs_readpage(struct file *file, struct page *page)
17
{
18
        return block_read_full_page(page,efs_get_block);
19
}
20
static int _efs_bmap(struct address_space *mapping, long block)
21
{
22
        return generic_block_bmap(mapping,block,efs_get_block);
23
}
24
struct address_space_operations efs_aops = {
25
        readpage: efs_readpage,
26
        sync_page: block_sync_page,
27
        bmap: _efs_bmap
28
};
29
 
30
static inline void extent_copy(efs_extent *src, efs_extent *dst) {
31
        /*
32
         * this is slightly evil. it doesn't just copy
33
         * efs_extent from src to dst, it also mangles
34
         * the bits so that dst ends up in cpu byte-order.
35
         */
36
 
37
        dst->cooked.ex_magic  =  (unsigned int) src->raw[0];
38
        dst->cooked.ex_bn     = ((unsigned int) src->raw[1] << 16) |
39
                                ((unsigned int) src->raw[2] <<  8) |
40
                                ((unsigned int) src->raw[3] <<  0);
41
        dst->cooked.ex_length =  (unsigned int) src->raw[4];
42
        dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) |
43
                                ((unsigned int) src->raw[6] <<  8) |
44
                                ((unsigned int) src->raw[7] <<  0);
45
        return;
46
}
47
 
48
void efs_read_inode(struct inode *inode) {
49
        int i, inode_index;
50
        dev_t device;
51
        struct buffer_head *bh;
52
        struct efs_sb_info    *sb = SUPER_INFO(inode->i_sb);
53
        struct efs_inode_info *in = INODE_INFO(inode);
54
        efs_block_t block, offset;
55
        struct efs_dinode *efs_inode;
56
 
57
        /*
58
        ** EFS layout:
59
        **
60
        ** |   cylinder group    |   cylinder group    |   cylinder group ..etc
61
        ** |inodes|data          |inodes|data          |inodes|data       ..etc
62
        **
63
        ** work out the inode block index, (considering initially that the
64
        ** inodes are stored as consecutive blocks). then work out the block
65
        ** number of that inode given the above layout, and finally the
66
        ** offset of the inode within that block.
67
        */
68
 
69
        inode_index = inode->i_ino /
70
                (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
71
 
72
        block = sb->fs_start + sb->first_block +
73
                (sb->group_size * (inode_index / sb->inode_blocks)) +
74
                (inode_index % sb->inode_blocks);
75
 
76
        offset = (inode->i_ino %
77
                        (EFS_BLOCKSIZE / sizeof(struct efs_dinode))) *
78
                sizeof(struct efs_dinode);
79
 
80
        bh = sb_bread(inode->i_sb, block);
81
        if (!bh) {
82
                printk(KERN_WARNING "EFS: bread() failed at block %d\n", block);
83
                goto read_inode_error;
84
        }
85
 
86
        efs_inode = (struct efs_dinode *) (bh->b_data + offset);
87
 
88
        inode->i_mode  = be16_to_cpu(efs_inode->di_mode);
89
        inode->i_nlink = be16_to_cpu(efs_inode->di_nlink);
90
        inode->i_uid   = (uid_t)be16_to_cpu(efs_inode->di_uid);
91
        inode->i_gid   = (gid_t)be16_to_cpu(efs_inode->di_gid);
92
        inode->i_size  = be32_to_cpu(efs_inode->di_size);
93
        inode->i_atime = be32_to_cpu(efs_inode->di_atime);
94
        inode->i_mtime = be32_to_cpu(efs_inode->di_mtime);
95
        inode->i_ctime = be32_to_cpu(efs_inode->di_ctime);
96
 
97
        /* this is the number of blocks in the file */
98
        if (inode->i_size == 0) {
99
                inode->i_blocks = 0;
100
        } else {
101
                inode->i_blocks = ((inode->i_size - 1) >> EFS_BLOCKSIZE_BITS) + 1;
102
        }
103
 
104
        /*
105
         * BUG: irix dev_t is 32-bits. linux dev_t is only 16-bits.
106
         *
107
         * apparently linux will change to 32-bit dev_t sometime during
108
         * linux 2.3.
109
         *
110
         * as is, this code maps devices that can't be represented in
111
         * 16-bits (ie major > 255 or minor > 255) to major = minor = 255.
112
         *
113
         * during 2.3 when 32-bit dev_t become available, we should test
114
         * to see whether odev contains 65535. if this is the case then we
115
         * should then do device = be32_to_cpu(efs_inode->di_u.di_dev.ndev).
116
         */
117
        device = be16_to_cpu(efs_inode->di_u.di_dev.odev);
118
 
119
        /* get the number of extents for this object */
120
        in->numextents = be16_to_cpu(efs_inode->di_numextents);
121
        in->lastextent = 0;
122
 
123
        /* copy the extents contained within the inode to memory */
124
        for(i = 0; i < EFS_DIRECTEXTENTS; i++) {
125
                extent_copy(&(efs_inode->di_u.di_extents[i]), &(in->extents[i]));
126
                if (i < in->numextents && in->extents[i].cooked.ex_magic != 0) {
127
                        printk(KERN_WARNING "EFS: extent %d has bad magic number in inode %lu\n", i, inode->i_ino);
128
                        brelse(bh);
129
                        goto read_inode_error;
130
                }
131
        }
132
 
133
        brelse(bh);
134
 
135
#ifdef DEBUG
136
        printk(KERN_DEBUG "EFS: read_inode(): inode %lu, extents %d, mode %o\n",
137
                inode->i_ino, in->numextents, inode->i_mode);
138
#endif
139
 
140
        switch (inode->i_mode & S_IFMT) {
141
                case S_IFDIR:
142
                        inode->i_op = &efs_dir_inode_operations;
143
                        inode->i_fop = &efs_dir_operations;
144
                        break;
145
                case S_IFREG:
146
                        inode->i_fop = &generic_ro_fops;
147
                        inode->i_data.a_ops = &efs_aops;
148
                        break;
149
                case S_IFLNK:
150
                        inode->i_op = &page_symlink_inode_operations;
151
                        inode->i_data.a_ops = &efs_symlink_aops;
152
                        break;
153
                case S_IFCHR:
154
                case S_IFBLK:
155
                case S_IFIFO:
156
                        init_special_inode(inode, inode->i_mode, device);
157
                        break;
158
                default:
159
                        printk(KERN_WARNING "EFS: unsupported inode mode %o\n", inode->i_mode);
160
                        goto read_inode_error;
161
                        break;
162
        }
163
 
164
        return;
165
 
166
read_inode_error:
167
        printk(KERN_WARNING "EFS: failed to read inode %lu\n", inode->i_ino);
168
        make_bad_inode(inode);
169
 
170
        return;
171
}
172
 
173
static inline efs_block_t
174
efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sb) {
175
        efs_block_t start;
176
        efs_block_t length;
177
        efs_block_t offset;
178
 
179
        /*
180
         * given an extent and a logical block within a file,
181
         * can this block be found within this extent ?
182
         */
183
        start  = ptr->cooked.ex_bn;
184
        length = ptr->cooked.ex_length;
185
        offset = ptr->cooked.ex_offset;
186
 
187
        if ((block >= offset) && (block < offset+length)) {
188
                return(sb->fs_start + start + block - offset);
189
        } else {
190
                return 0;
191
        }
192
}
193
 
194
efs_block_t efs_map_block(struct inode *inode, efs_block_t block) {
195
        struct efs_sb_info    *sb = SUPER_INFO(inode->i_sb);
196
        struct efs_inode_info *in = INODE_INFO(inode);
197
        struct buffer_head    *bh = NULL;
198
 
199
        int cur, last, first = 1;
200
        int ibase, ioffset, dirext, direxts, indext, indexts;
201
        efs_block_t iblock, result = 0, lastblock = 0;
202
        efs_extent ext, *exts;
203
 
204
        last = in->lastextent;
205
 
206
        if (in->numextents <= EFS_DIRECTEXTENTS) {
207
                /* first check the last extent we returned */
208
                if ((result = efs_extent_check(&in->extents[last], block, sb)))
209
                        return result;
210
 
211
                /* if we only have one extent then nothing can be found */
212
                if (in->numextents == 1) {
213
                        printk(KERN_ERR "EFS: map_block() failed to map (1 extent)\n");
214
                        return 0;
215
                }
216
 
217
                direxts = in->numextents;
218
 
219
                /*
220
                 * check the stored extents in the inode
221
                 * start with next extent and check forwards
222
                 */
223
                for(dirext = 1; dirext < direxts; dirext++) {
224
                        cur = (last + dirext) % in->numextents;
225
                        if ((result = efs_extent_check(&in->extents[cur], block, sb))) {
226
                                in->lastextent = cur;
227
                                return result;
228
                        }
229
                }
230
 
231
                printk(KERN_ERR "EFS: map_block() failed to map block %u (dir)\n", block);
232
                return 0;
233
        }
234
 
235
#ifdef DEBUG
236
        printk(KERN_DEBUG "EFS: map_block(): indirect search for logical block %u\n", block);
237
#endif
238
        direxts = in->extents[0].cooked.ex_offset;
239
        indexts = in->numextents;
240
 
241
        for(indext = 0; indext < indexts; indext++) {
242
                cur = (last + indext) % indexts;
243
 
244
                /*
245
                 * work out which direct extent contains `cur'.
246
                 *
247
                 * also compute ibase: i.e. the number of the first
248
                 * indirect extent contained within direct extent `cur'.
249
                 *
250
                 */
251
                ibase = 0;
252
                for(dirext = 0; cur < ibase && dirext < direxts; dirext++) {
253
                        ibase += in->extents[dirext].cooked.ex_length *
254
                                (EFS_BLOCKSIZE / sizeof(efs_extent));
255
                }
256
 
257
                if (dirext == direxts) {
258
                        /* should never happen */
259
                        printk(KERN_ERR "EFS: couldn't find direct extent for indirect extent %d (block %u)\n", cur, block);
260
                        if (bh) brelse(bh);
261
                        return 0;
262
                }
263
 
264
                /* work out block number and offset of this indirect extent */
265
                iblock = sb->fs_start + in->extents[dirext].cooked.ex_bn +
266
                        (cur - ibase) /
267
                        (EFS_BLOCKSIZE / sizeof(efs_extent));
268
                ioffset = (cur - ibase) %
269
                        (EFS_BLOCKSIZE / sizeof(efs_extent));
270
 
271
                if (first || lastblock != iblock) {
272
                        if (bh) brelse(bh);
273
 
274
                        bh = sb_bread(inode->i_sb, iblock);
275
                        if (!bh) {
276
                                printk(KERN_ERR "EFS: bread() failed at block %d\n", iblock);
277
                                return 0;
278
                        }
279
#ifdef DEBUG
280
                        printk(KERN_DEBUG "EFS: map_block(): read indirect extent block %d\n", iblock);
281
#endif
282
                        first = 0;
283
                        lastblock = iblock;
284
                }
285
 
286
                exts = (efs_extent *) bh->b_data;
287
 
288
                extent_copy(&(exts[ioffset]), &ext);
289
 
290
                if (ext.cooked.ex_magic != 0) {
291
                        printk(KERN_ERR "EFS: extent %d has bad magic number in block %d\n", cur, iblock);
292
                        if (bh) brelse(bh);
293
                        return 0;
294
                }
295
 
296
                if ((result = efs_extent_check(&ext, block, sb))) {
297
                        if (bh) brelse(bh);
298
                        in->lastextent = cur;
299
                        return result;
300
                }
301
        }
302
        if (bh) brelse(bh);
303
        printk(KERN_ERR "EFS: map_block() failed to map block %u (indir)\n", block);
304
        return 0;
305
}
306
 
307
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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