The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/bfs/file.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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         llseek: generic_file_llseek,
   23         read:   generic_file_read,
   24         write:  generic_file_write,
   25         mmap:   generic_file_mmap,
   26 };
   27 
   28 static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
   29 {
   30         struct buffer_head *bh, *new;
   31 
   32         bh = bread(dev, from, BFS_BSIZE);
   33         if (!bh)
   34                 return -EIO;
   35         new = getblk(dev, to, BFS_BSIZE);
   36         memcpy(new->b_data, bh->b_data, bh->b_size);
   37         mark_buffer_dirty(new);
   38         bforget(bh);
   39         brelse(new);
   40         return 0;
   41 }
   42 
   43 static int bfs_move_blocks(kdev_t dev, unsigned long start, unsigned long end, 
   44                                 unsigned long where)
   45 {
   46         unsigned long i;
   47 
   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);
   52                         return -EIO;
   53                 }
   54         return 0;
   55 }
   56 
   57 static int bfs_get_block(struct inode * inode, long block, 
   58         struct buffer_head * bh_result, int create)
   59 {
   60         long phys;
   61         int err;
   62         struct super_block *sb = inode->i_sb;
   63         struct buffer_head *sbh = sb->su_sbh;
   64 
   65         if (block < 0 || block > sb->su_blocks)
   66                 return -EIO;
   67 
   68         phys = inode->iu_sblock + block;
   69         if (!create) {
   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);
   75                 }
   76                 return 0;
   77         }
   78 
   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", 
   83                                 create, block, phys);
   84                 bh_result->b_dev = inode->i_dev;
   85                 bh_result->b_blocknr = phys;
   86                 bh_result->b_state |= (1UL << BH_Mapped);
   87                 return 0;
   88         }
   89 
   90         /* the rest has to be protected against itself */
   91         lock_kernel();
   92 
   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", 
   97                                 create, block, phys);
   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);
  105                 err = 0;
  106                 goto out;
  107         }
  108 
  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);
  114                 if (err) {
  115                         dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino);
  116                         goto out;
  117                 }
  118         } else
  119                 err = 0;
  120 
  121         dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", create, block, phys);
  122         inode->iu_sblock = phys;
  123         phys += block;
  124         sb->su_lf_eblk = inode->iu_eblock = phys;
  125 
  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);
  134 out:
  135         unlock_kernel();
  136         return err;
  137 }
  138 
  139 static int bfs_writepage(struct page *page)
  140 {
  141         return block_write_full_page(page, bfs_get_block);
  142 }
  143 
  144 static int bfs_readpage(struct file *file, struct page *page)
  145 {
  146         return block_read_full_page(page, bfs_get_block);
  147 }
  148 
  149 static int bfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
  150 {
  151         return block_prepare_write(page, from, to, bfs_get_block);
  152 }
  153 
  154 static int bfs_bmap(struct address_space *mapping, long block)
  155 {
  156         return generic_block_bmap(mapping, block, bfs_get_block);
  157 }
  158 
  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,
  165         bmap:           bfs_bmap,
  166 };
  167 
  168 struct inode_operations bfs_file_inops;

Cache object: 7bdd9c570deb94651bb50154b16d33a0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.