file.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
- /*
- * fs/bfs/file.c
- * BFS file operations.
- * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
- */
- #include <linux/fs.h>
- #include <linux/locks.h>
- #include <linux/bfs_fs.h>
- #include <linux/smp_lock.h>
- #include "bfs_defs.h"
- #undef DEBUG
- #ifdef DEBUG
- #define dprintf(x...) printf(x)
- #else
- #define dprintf(x...)
- #endif
- struct file_operations bfs_file_operations = {
- llseek: generic_file_llseek,
- read: generic_file_read,
- write: generic_file_write,
- mmap: generic_file_mmap,
- };
- static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
- {
- struct buffer_head *bh, *new;
- bh = bread(dev, from, BFS_BSIZE);
- if (!bh)
- return -EIO;
- new = getblk(dev, to, BFS_BSIZE);
- memcpy(new->b_data, bh->b_data, bh->b_size);
- mark_buffer_dirty(new);
- bforget(bh);
- brelse(new);
- return 0;
- }
- static int bfs_move_blocks(kdev_t dev, unsigned long start, unsigned long end,
- unsigned long where)
- {
- unsigned long i;
- dprintf("%08lx-%08lx->%08lxn", start, end, where);
- for (i = start; i <= end; i++)
- if(bfs_move_block(i, where + i, dev)) {
- dprintf("failed to move block %08lx -> %08lxn", i, where + i);
- return -EIO;
- }
- return 0;
- }
- static int bfs_get_block(struct inode * inode, long block,
- struct buffer_head * bh_result, int create)
- {
- long phys;
- int err;
- struct super_block *sb = inode->i_sb;
- struct buffer_head *sbh = sb->su_sbh;
- if (block < 0 || block > sb->su_blocks)
- return -EIO;
- phys = inode->iu_sblock + block;
- if (!create) {
- if (phys <= inode->iu_eblock) {
- dprintf("c=%d, b=%08lx, phys=%08lx (granted)n", create, block, phys);
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- }
- return 0;
- }
- /* if the file is not empty and the requested block is within the range
- of blocks allocated for this file, we can grant it */
- if (inode->i_size && phys <= inode->iu_eblock) {
- dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)n",
- create, block, phys);
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- return 0;
- }
- /* the rest has to be protected against itself */
- lock_kernel();
- /* if the last data block for this file is the last allocated block, we can
- extend the file trivially, without moving it anywhere */
- if (inode->iu_eblock == sb->su_lf_eblk) {
- dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)n",
- create, block, phys);
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- sb->su_freeb -= phys - inode->iu_eblock;
- sb->su_lf_eblk = inode->iu_eblock = phys;
- mark_inode_dirty(inode);
- mark_buffer_dirty(sbh);
- err = 0;
- goto out;
- }
- /* Ok, we have to move this entire file to the next free block */
- phys = sb->su_lf_eblk + 1;
- if (inode->iu_sblock) { /* if data starts on block 0 then there is no data */
- err = bfs_move_blocks(inode->i_dev, inode->iu_sblock,
- inode->iu_eblock, phys);
- if (err) {
- dprintf("failed to move ino=%08lx -> fs corruptionn", inode->i_ino);
- goto out;
- }
- } else
- err = 0;
- dprintf("c=%d, b=%08lx, phys=%08lx (moved)n", create, block, phys);
- inode->iu_sblock = phys;
- phys += block;
- sb->su_lf_eblk = inode->iu_eblock = phys;
- /* this assumes nothing can write the inode back while we are here
- * and thus update inode->i_blocks! (XXX)*/
- sb->su_freeb -= inode->iu_eblock - inode->iu_sblock + 1 - inode->i_blocks;
- mark_inode_dirty(inode);
- mark_buffer_dirty(sbh);
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- out:
- unlock_kernel();
- return err;
- }
- static int bfs_writepage(struct page *page)
- {
- return block_write_full_page(page, bfs_get_block);
- }
- static int bfs_readpage(struct file *file, struct page *page)
- {
- return block_read_full_page(page, bfs_get_block);
- }
- static int bfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
- {
- return block_prepare_write(page, from, to, bfs_get_block);
- }
- static int bfs_bmap(struct address_space *mapping, long block)
- {
- return generic_block_bmap(mapping, block, bfs_get_block);
- }
- struct address_space_operations bfs_aops = {
- readpage: bfs_readpage,
- writepage: bfs_writepage,
- sync_page: block_sync_page,
- prepare_write: bfs_prepare_write,
- commit_write: generic_commit_write,
- bmap: bfs_bmap,
- };
- struct inode_operations bfs_file_inops;