~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/bfs/file.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  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         read:   generic_file_read,
 23         write:  generic_file_write,
 24         mmap:   generic_file_mmap,
 25 };
 26 
 27 static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
 28 {
 29         struct buffer_head *bh, *new;
 30 
 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;
 40 }
 41 
 42 static int bfs_move_blocks(kdev_t dev, unsigned long start, unsigned long end, 
 43                                 unsigned long where)
 44 {
 45         unsigned long i;
 46 
 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;
 52                 }
 53         return 0;
 54 }
 55 
 56 static int bfs_get_block(struct inode * inode, long block, 
 57         struct buffer_head * bh_result, int create)
 58 {
 59         long phys;
 60         int err;
 61         struct super_block *sb = inode->i_sb;
 62         struct buffer_head *sbh = sb->su_sbh;
 63 
 64         if (block < 0 || block > sb->su_blocks)
 65                 return -EIO;
 66 
 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);
 74                 }
 75                 return 0;
 76         }
 77 
 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;
 87         }
 88 
 89         /* the rest has to be protected against itself */
 90         lock_kernel();
 91 
 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;
106         }
107 
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;
116                 }
117         } else
118                 err = 0;
119 
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;
124 
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;
136 }
137 
138 static int bfs_writepage(struct page *page)
139 {
140         return block_write_full_page(page, bfs_get_block);
141 }
142 
143 static int bfs_readpage(struct file *file, struct page *page)
144 {
145         return block_read_full_page(page, bfs_get_block);
146 }
147 
148 static int bfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
149 {
150         return block_prepare_write(page, from, to, bfs_get_block);
151 }
152 
153 static int bfs_bmap(struct address_space *mapping, long block)
154 {
155         return generic_block_bmap(mapping, block, bfs_get_block);
156 }
157 
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,
165 };
166 
167 struct inode_operations bfs_file_inops;
168 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.