4 * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
8 #include <linux/locks.h>
9 #include <linux/bfs_fs.h>
10 #include <linux/smp_lock.h>
16 #define dprintf(x...) printf(x)
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,
28 static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
30 struct buffer_head *bh, *new;
32 bh = bread(dev, from, BFS_BSIZE);
35 new = getblk(dev, to, BFS_BSIZE);
36 memcpy(new->b_data, bh->b_data, bh->b_size);
37 mark_buffer_dirty(new);
43 static int bfs_move_blocks(kdev_t dev, unsigned long start, unsigned long end,
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);
57 static int bfs_get_block(struct inode * inode, long block,
58 struct buffer_head * bh_result, int create)
62 struct super_block *sb = inode->i_sb;
63 struct buffer_head *sbh = sb->su_sbh;
65 if (block < 0 || block > sb->su_blocks)
68 phys = inode->iu_sblock + block;
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);
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",
84 bh_result->b_dev = inode->i_dev;
85 bh_result->b_blocknr = phys;
86 bh_result->b_state |= (1UL << BH_Mapped);
90 /* the rest has to be protected against itself */
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",
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);
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);
115 dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino);
121 dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", create, block, phys);
122 inode->iu_sblock = phys;
124 sb->su_lf_eblk = inode->iu_eblock = phys;
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);
139 static int bfs_writepage(struct page *page)
141 return block_write_full_page(page, bfs_get_block);
144 static int bfs_readpage(struct file *file, struct page *page)
146 return block_read_full_page(page, bfs_get_block);
149 static int bfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
151 return block_prepare_write(page, from, to, bfs_get_block);
154 static int bfs_bmap(struct address_space *mapping, long block)
156 return generic_block_bmap(mapping, block, bfs_get_block);
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,
168 struct inode_operations bfs_file_inops;