Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.6.24 /fs/bfs/file.c

Filename:/fs/bfs/file.c
Lines Added:49
Lines Deleted:25
Also changed in: (Previous) 2.6.24-rc8  2.6.24-rc7  2.6.24-rc6  2.6.24-rc5  2.6.24-rc4  2.6.24-rc3 
(Following) 2.6.26-git15  2.6.26-git16  2.6.26-git17  2.6.26-git18  2.6.27-rc1  2.6.27-rc2 

Location
[  2.6.24
  [  fs
    [  bfs
       o  file.c

Patch

diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index 24310e9..b11e63e 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -2,6 +2,11 @@
  *   fs/bfs/file.c
  *   BFS file operations.
  *   Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
+ *
+ *   Make the file block allocation algorithm understand the size
+ *   of the underlying block device.
+ *   Copyright (C) 2007 Dmitri Vorobiev <dmitri.vorobiev@gmail.com>
+ *
  */
 
 #include <linux/fs.h>
@@ -27,7 +32,8 @@ const struct file_operations bfs_file_operations = {
    .splice_read   = generic_file_splice_read,
 };
 
-static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb)
+static int bfs_move_block(unsigned long from, unsigned long to,
+               struct super_block *sb)
 {
    struct buffer_head *bh, *new;
 
@@ -43,21 +49,22 @@ static int bfs_move_block(unsigned long from, unsigned long to, struct super_blo
 }
 
 static int bfs_move_blocks(struct super_block *sb, unsigned long start,
-                           unsigned long end, unsigned long where)
+            unsigned long end, unsigned long where)
 {
    unsigned long i;
 
    dprintf("%08lx-%08lx->%08lx\n", start, end, where);
    for (i = start; i <= end; i++)
       if(bfs_move_block(i, where + i, sb)) {
-         dprintf("failed to move block %08lx -> %08lx\n", i, where + i);
+         dprintf("failed to move block %08lx -> %08lx\n", i,
+                        where + i);
          return -EIO;
       }
    return 0;
 }
 
-static int bfs_get_block(struct inode * inode, sector_t block, 
-   struct buffer_head * bh_result, int create)
+static int bfs_get_block(struct inode *inode, sector_t block,
+         struct buffer_head *bh_result, int create)
 {
    unsigned long phys;
    int err;
@@ -66,9 +73,6 @@ static int bfs_get_block(struct inode * inode, sector_t block,
    struct bfs_inode_info *bi = BFS_I(inode);
    struct buffer_head *sbh = info->si_sbh;
 
-   if (block > info->si_blocks)
-      return -EIO;
-
    phys = bi->i_sblock + block;
    if (!create) {
       if (phys <= bi->i_eblock) {
@@ -79,21 +83,29 @@ static int bfs_get_block(struct inode * inode, sector_t block,
       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 <= bi->i_eblock) {
+   /*
+    * 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 (bi->i_sblock && (phys <= bi->i_eblock)) {
       dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", 
             create, (unsigned long)block, phys);
       map_bh(bh_result, sb, phys);
       return 0;
    }
 
-   /* the rest has to be protected against itself */
+   /* The file will be extended, so let's see if there is enough space. */
+   if (phys >= info->si_blocks)
+      return -ENOSPC;
+
+   /* 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 the last data block for this file is the last allocated
+    * block, we can extend the file trivially, without moving it
+    * anywhere.
+    */
    if (bi->i_eblock == info->si_lf_eblk) {
       dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", 
             create, (unsigned long)block, phys);
@@ -106,13 +118,19 @@ static int bfs_get_block(struct inode * inode, sector_t block,
       goto out;
    }
 
-   /* Ok, we have to move this entire file to the next free block */
+   /* Ok, we have to move this entire file to the next free block. */
    phys = info->si_lf_eblk + 1;
-   if (bi->i_sblock) { /* if data starts on block 0 then there is no data */
+   if (phys + block >= info->si_blocks) {
+      err = -ENOSPC;
+      goto out;
+   }
+
+   if (bi->i_sblock) {
       err = bfs_move_blocks(inode->i_sb, bi->i_sblock, 
-            bi->i_eblock, phys);
+                  bi->i_eblock, phys);
       if (err) {
-         dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino);
+         dprintf("failed to move ino=%08lx -> fs corruption\n",
+                        inode->i_ino);
          goto out;
       }
    } else
@@ -124,8 +142,10 @@ static int bfs_get_block(struct inode * inode, sector_t block,
    phys += block;
    info->si_lf_eblk = bi->i_eblock = phys;
 
-   /* this assumes nothing can write the inode back while we are here
-    * and thus update inode->i_blocks! (XXX)*/
+   /*
+    * This assumes nothing can write the inode back while we are here
+    * and thus update inode->i_blocks! (XXX)
+    */
    info->si_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks;
    mark_inode_dirty(inode);
    mark_buffer_dirty(sbh);
@@ -145,9 +165,13 @@ 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)
+static int bfs_write_begin(struct file *file, struct address_space *mapping,
+         loff_t pos, unsigned len, unsigned flags,
+         struct page **pagep, void **fsdata)
 {
-   return block_prepare_write(page, from, to, bfs_get_block);
+   *pagep = NULL;
+   return block_write_begin(file, mapping, pos, len, flags,
+               pagep, fsdata, bfs_get_block);
 }
 
 static sector_t bfs_bmap(struct address_space *mapping, sector_t block)
@@ -159,8 +183,8 @@ const 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,
+   .write_begin   = bfs_write_begin,
+   .write_end   = generic_write_end,
    .bmap      = bfs_bmap,
 };
 


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.