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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [bfs/] [file.c] - Blame information for rev 1774

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

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      fs/bfs/file.c
3
 *      BFS file operations.
4
 *      Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
5
 */
6
 
7
#include <linux/fs.h>
8
#include <linux/locks.h>
9
#include <linux/bfs_fs.h>
10
#include <linux/smp_lock.h>
11
#include "bfs_defs.h"
12
 
13
#undef DEBUG
14
 
15
#ifdef DEBUG
16
#define dprintf(x...)   printf(x)
17
#else
18
#define dprintf(x...)
19
#endif
20
 
21
struct file_operations bfs_file_operations = {
22
        llseek: generic_file_llseek,
23
        read:   generic_file_read,
24
        write:  generic_file_write,
25
        mmap:   generic_file_mmap,
26
};
27
 
28
static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
29
{
30
        struct buffer_head *bh, *new;
31
 
32
        bh = bread(dev, from, BFS_BSIZE);
33
        if (!bh)
34
                return -EIO;
35
        new = getblk(dev, to, BFS_BSIZE);
36
        memcpy(new->b_data, bh->b_data, bh->b_size);
37
        mark_buffer_dirty(new);
38
        bforget(bh);
39
        brelse(new);
40
        return 0;
41
}
42
 
43
static int bfs_move_blocks(kdev_t dev, unsigned long start, unsigned long end,
44
                                unsigned long where)
45
{
46
        unsigned long i;
47
 
48
        dprintf("%08lx-%08lx->%08lx\n", start, end, where);
49
        for (i = start; i <= end; i++)
50
                if(bfs_move_block(i, where + i, dev)) {
51
                        dprintf("failed to move block %08lx -> %08lx\n", i, where + i);
52
                        return -EIO;
53
                }
54
        return 0;
55
}
56
 
57
static int bfs_get_block(struct inode * inode, long block,
58
        struct buffer_head * bh_result, int create)
59
{
60
        long phys;
61
        int err;
62
        struct super_block *sb = inode->i_sb;
63
        struct buffer_head *sbh = sb->su_sbh;
64
 
65
        if (block < 0 || block > sb->su_blocks)
66
                return -EIO;
67
 
68
        phys = inode->iu_sblock + block;
69
        if (!create) {
70
                if (phys <= inode->iu_eblock) {
71
                        dprintf("c=%d, b=%08lx, phys=%08lx (granted)\n", create, block, phys);
72
                        bh_result->b_dev = inode->i_dev;
73
                        bh_result->b_blocknr = phys;
74
                        bh_result->b_state |= (1UL << BH_Mapped);
75
                }
76
                return 0;
77
        }
78
 
79
        /* if the file is not empty and the requested block is within the range
80
           of blocks allocated for this file, we can grant it */
81
        if (inode->i_size && phys <= inode->iu_eblock) {
82
                dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n",
83
                                create, block, phys);
84
                bh_result->b_dev = inode->i_dev;
85
                bh_result->b_blocknr = phys;
86
                bh_result->b_state |= (1UL << BH_Mapped);
87
                return 0;
88
        }
89
 
90
        /* the rest has to be protected against itself */
91
        lock_kernel();
92
 
93
        /* if the last data block for this file is the last allocated block, we can
94
           extend the file trivially, without moving it anywhere */
95
        if (inode->iu_eblock == sb->su_lf_eblk) {
96
                dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n",
97
                                create, block, phys);
98
                bh_result->b_dev = inode->i_dev;
99
                bh_result->b_blocknr = phys;
100
                bh_result->b_state |= (1UL << BH_Mapped);
101
                sb->su_freeb -= phys - inode->iu_eblock;
102
                sb->su_lf_eblk = inode->iu_eblock = phys;
103
                mark_inode_dirty(inode);
104
                mark_buffer_dirty(sbh);
105
                err = 0;
106
                goto out;
107
        }
108
 
109
        /* Ok, we have to move this entire file to the next free block */
110
        phys = sb->su_lf_eblk + 1;
111
        if (inode->iu_sblock) { /* if data starts on block 0 then there is no data */
112
                err = bfs_move_blocks(inode->i_dev, inode->iu_sblock,
113
                                inode->iu_eblock, phys);
114
                if (err) {
115
                        dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino);
116
                        goto out;
117
                }
118
        } else
119
                err = 0;
120
 
121
        dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", create, block, phys);
122
        inode->iu_sblock = phys;
123
        phys += block;
124
        sb->su_lf_eblk = inode->iu_eblock = phys;
125
 
126
        /* this assumes nothing can write the inode back while we are here
127
         * and thus update inode->i_blocks! (XXX)*/
128
        sb->su_freeb -= inode->iu_eblock - inode->iu_sblock + 1 - inode->i_blocks;
129
        mark_inode_dirty(inode);
130
        mark_buffer_dirty(sbh);
131
        bh_result->b_dev = inode->i_dev;
132
        bh_result->b_blocknr = phys;
133
        bh_result->b_state |= (1UL << BH_Mapped);
134
out:
135
        unlock_kernel();
136
        return err;
137
}
138
 
139
static int bfs_writepage(struct page *page)
140
{
141
        return block_write_full_page(page, bfs_get_block);
142
}
143
 
144
static int bfs_readpage(struct file *file, struct page *page)
145
{
146
        return block_read_full_page(page, bfs_get_block);
147
}
148
 
149
static int bfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
150
{
151
        return block_prepare_write(page, from, to, bfs_get_block);
152
}
153
 
154
static int bfs_bmap(struct address_space *mapping, long block)
155
{
156
        return generic_block_bmap(mapping, block, bfs_get_block);
157
}
158
 
159
struct address_space_operations bfs_aops = {
160
        readpage:       bfs_readpage,
161
        writepage:      bfs_writepage,
162
        sync_page:      block_sync_page,
163
        prepare_write:  bfs_prepare_write,
164
        commit_write:   generic_commit_write,
165
        bmap:           bfs_bmap,
166
};
167
 
168
struct inode_operations bfs_file_inops;

powered by: WebSVN 2.1.0

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