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 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
);
34 new = getblk(dev
, to
, BFS_BSIZE
);
35 memcpy(new->b_data
, bh
->b_data
, bh
->b_size
);
36 mark_buffer_dirty(new);
42 static int bfs_move_blocks(kdev_t dev
, unsigned long start
, unsigned long end
,
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
);
56 static int bfs_get_block(struct inode
* inode
, long block
,
57 struct buffer_head
* bh_result
, int create
)
61 struct super_block
*sb
= inode
->i_sb
;
62 struct buffer_head
*sbh
= sb
->su_sbh
;
64 if (block
< 0 || block
> sb
->su_blocks
)
67 phys
= inode
->iu_sblock
+ block
;
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
);
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",
83 bh_result
->b_dev
= inode
->i_dev
;
84 bh_result
->b_blocknr
= phys
;
85 bh_result
->b_state
|= (1UL << BH_Mapped
);
89 /* the rest has to be protected against itself */
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",
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
);
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
);
114 dprintf("failed to move ino=%08lx -> fs corruption\n", inode
->i_ino
);
120 dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", create
, block
, phys
);
121 inode
->iu_sblock
= phys
;
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
);
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
,
167 struct inode_operations bfs_file_inops
;