Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / fs / bfs / file.c
blobde63fb2de2c947dd49b0956b17162932dcb64ce1
1 /*
2 * fs/bfs/file.c
3 * BFS file operations.
4 * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
5 */
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"
13 #undef DEBUG
15 #ifdef DEBUG
16 #define dprintf(x...) printf(x)
17 #else
18 #define dprintf(x...)
19 #endif
21 struct file_operations bfs_file_operations = {
22 read: generic_file_read,
23 write: generic_file_write,
24 mmap: generic_file_mmap,
27 static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
29 struct buffer_head *bh, *new;
31 bh = bread(dev, from, BFS_BSIZE);
32 if (!bh)
33 return -EIO;
34 new = getblk(dev, to, BFS_BSIZE);
35 memcpy(new->b_data, bh->b_data, bh->b_size);
36 mark_buffer_dirty(new);
37 bforget(bh);
38 brelse(new);
39 return 0;
42 static int bfs_move_blocks(kdev_t dev, unsigned long start, unsigned long end,
43 unsigned long where)
45 unsigned long i;
47 dprintf("%08lx-%08lx->%08lx\n", start, end, where);
48 for (i = start; i <= end; i++)
49 if(bfs_move_block(i, where + i, dev)) {
50 dprintf("failed to move block %08lx -> %08lx\n", i, where + i);
51 return -EIO;
53 return 0;
56 static int bfs_get_block(struct inode * inode, long block,
57 struct buffer_head * bh_result, int create)
59 long phys;
60 int err;
61 struct super_block *sb = inode->i_sb;
62 struct buffer_head *sbh = sb->su_sbh;
64 if (block < 0 || block > sb->su_blocks)
65 return -EIO;
67 phys = inode->iu_sblock + block;
68 if (!create) {
69 if (phys <= inode->iu_eblock) {
70 dprintf("c=%d, b=%08lx, phys=%08lx (granted)\n", create, block, phys);
71 bh_result->b_dev = inode->i_dev;
72 bh_result->b_blocknr = phys;
73 bh_result->b_state |= (1UL << BH_Mapped);
75 return 0;
78 /* if the file is not empty and the requested block is within the range
79 of blocks allocated for this file, we can grant it */
80 if (inode->i_size && phys <= inode->iu_eblock) {
81 dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n",
82 create, block, phys);
83 bh_result->b_dev = inode->i_dev;
84 bh_result->b_blocknr = phys;
85 bh_result->b_state |= (1UL << BH_Mapped);
86 return 0;
89 /* the rest has to be protected against itself */
90 lock_kernel();
92 /* if the last data block for this file is the last allocated block, we can
93 extend the file trivially, without moving it anywhere */
94 if (inode->iu_eblock == sb->su_lf_eblk) {
95 dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n",
96 create, block, phys);
97 bh_result->b_dev = inode->i_dev;
98 bh_result->b_blocknr = phys;
99 bh_result->b_state |= (1UL << BH_Mapped);
100 sb->su_freeb -= phys - inode->iu_eblock;
101 sb->su_lf_eblk = inode->iu_eblock = phys;
102 mark_inode_dirty(inode);
103 mark_buffer_dirty(sbh);
104 err = 0;
105 goto out;
108 /* Ok, we have to move this entire file to the next free block */
109 phys = sb->su_lf_eblk + 1;
110 if (inode->iu_sblock) { /* if data starts on block 0 then there is no data */
111 err = bfs_move_blocks(inode->i_dev, inode->iu_sblock,
112 inode->iu_eblock, phys);
113 if (err) {
114 dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino);
115 goto out;
117 } else
118 err = 0;
120 dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", create, block, phys);
121 inode->iu_sblock = phys;
122 phys += block;
123 sb->su_lf_eblk = inode->iu_eblock = phys;
125 /* this assumes nothing can write the inode back while we are here
126 * and thus update inode->i_blocks! (XXX)*/
127 sb->su_freeb -= inode->iu_eblock - inode->iu_sblock + 1 - inode->i_blocks;
128 mark_inode_dirty(inode);
129 mark_buffer_dirty(sbh);
130 bh_result->b_dev = inode->i_dev;
131 bh_result->b_blocknr = phys;
132 bh_result->b_state |= (1UL << BH_Mapped);
133 out:
134 unlock_kernel();
135 return err;
138 static int bfs_writepage(struct page *page)
140 return block_write_full_page(page, bfs_get_block);
143 static int bfs_readpage(struct file *file, struct page *page)
145 return block_read_full_page(page, bfs_get_block);
148 static int bfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
150 return block_prepare_write(page, from, to, bfs_get_block);
153 static int bfs_bmap(struct address_space *mapping, long block)
155 return generic_block_bmap(mapping, block, bfs_get_block);
158 struct address_space_operations bfs_aops = {
159 readpage: bfs_readpage,
160 writepage: bfs_writepage,
161 sync_page: block_sync_page,
162 prepare_write: bfs_prepare_write,
163 commit_write: generic_commit_write,
164 bmap: bfs_bmap,
167 struct inode_operations bfs_file_inops;