root/fs/msdos/buffer.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. msdos_bread
  2. msdos_getblk
  3. msdos_brelse
  4. msdos_mark_buffer_dirty
  5. msdos_set_uptodate
  6. msdos_is_uptodate
  7. msdos_ll_rw_block

   1 #include <linux/mm.h>
   2 #include <linux/malloc.h>
   3 #include <linux/string.h>
   4 #include <linux/fs.h>
   5 #include <linux/msdos_fs.h>
   6 
   7 struct buffer_head *msdos_bread (
     /* [previous][next][first][last][top][bottom][index][help] */
   8         struct super_block *sb,
   9         int block)
  10 {
  11         struct buffer_head *ret = NULL;
  12         if (sb->s_blocksize == 512){
  13                 ret = bread (sb->s_dev,block,512);
  14         }else{
  15                 struct buffer_head *real = bread (sb->s_dev,block>>1,1024);
  16                 if (real != NULL){
  17                         ret = (struct buffer_head *)kmalloc (sizeof(struct buffer_head)
  18                                 ,GFP_KERNEL);
  19                         if (ret != NULL){
  20                                 /* #Specification: msdos / strategy / special device / dummy blocks
  21                                         Many special device (Scsi optical disk for one) use
  22                                         larger hardware sector size. This allows for higher
  23                                         capacity.
  24 
  25                                         Most of the time, the MsDOS file system that sit
  26                                         on this device is totally unaligned. It use logically
  27                                         512 bytes sector size, with logical sector starting
  28                                         in the middle of a hardware block. The bad news is
  29                                         that a hardware sector may hold data own by two
  30                                         different files. This means that the hardware sector
  31                                         must be read, patch and written almost all the time.
  32 
  33                                         Needless to say that it kills write performance
  34                                         on all OS.
  35 
  36                                         Internally the linux msdos fs is using 512 bytes
  37                                         logical sector. When accessing such a device, we
  38                                         allocate dummy buffer cache blocks, that we stuff
  39                                         with the information of a real one (1k large).
  40 
  41                                         This strategy is used to hide this difference to
  42                                         the core of the msdos fs. The slowdown is not
  43                                         hidden though!
  44                                 */
  45                                 /*
  46                                         The memset is there only to catch errors. The msdos
  47                                         fs is only using b_data
  48                                 */
  49                                 memset (ret,0,sizeof(*ret));
  50                                 ret->b_data = real->b_data;
  51                                 if (block & 1) ret->b_data += 512;
  52                                 ret->b_next = real;
  53                         }else{
  54                                 brelse (real);
  55                         }
  56                 }
  57         }
  58         return ret;
  59 }
  60 struct buffer_head *msdos_getblk (
     /* [previous][next][first][last][top][bottom][index][help] */
  61         struct super_block *sb,
  62         int block)
  63 {
  64         struct buffer_head *ret = NULL;
  65         if (sb->s_blocksize == 512){
  66                 ret = getblk (sb->s_dev,block,512);
  67         }else{
  68                 /* #Specification: msdos / special device / writing
  69                         A write is always preceded by a read of the complete block
  70                         (large hardware sector size). This defeat write performance.
  71                         There is a possibility to optimize this when writing large
  72                         chunk by making sure we are filling large block. Volunteer ?
  73                 */
  74                 ret = msdos_bread (sb,block);
  75         }
  76         return ret;
  77 }
  78 
  79 void msdos_brelse (
     /* [previous][next][first][last][top][bottom][index][help] */
  80         struct super_block *sb,
  81         struct buffer_head *bh)
  82 {
  83         if (bh != NULL){
  84                 if (sb->s_blocksize == 512){
  85                         brelse (bh);
  86                 }else{
  87                         brelse (bh->b_next);
  88                         /* We can free the dummy because a new one is allocated at
  89                                 each msdos_getblk() and msdos_bread().
  90                         */
  91                         kfree (bh);
  92                 }
  93         }
  94 }
  95         
  96 void msdos_mark_buffer_dirty (
     /* [previous][next][first][last][top][bottom][index][help] */
  97         struct super_block *sb,
  98         struct buffer_head *bh,
  99         int dirty_val)
 100 {
 101         if (sb->s_blocksize != 512){
 102                 bh = bh->b_next;
 103         }
 104         mark_buffer_dirty (bh,dirty_val);
 105 }
 106 
 107 void msdos_set_uptodate (
     /* [previous][next][first][last][top][bottom][index][help] */
 108         struct super_block *sb,
 109         struct buffer_head *bh,
 110         int val)
 111 {
 112         if (sb->s_blocksize != 512){
 113                 bh = bh->b_next;
 114         }
 115         bh->b_uptodate = val;
 116 }
 117 int msdos_is_uptodate (
     /* [previous][next][first][last][top][bottom][index][help] */
 118         struct super_block *sb,
 119         struct buffer_head *bh)
 120 {
 121         if (sb->s_blocksize != 512){
 122                 bh = bh->b_next;
 123         }
 124         return bh->b_uptodate;
 125 }
 126 
 127 void msdos_ll_rw_block (
     /* [previous][next][first][last][top][bottom][index][help] */
 128         struct super_block *sb,
 129         int opr,
 130         int nbreq,
 131         struct buffer_head *bh[32])
 132 {
 133         if (sb->s_blocksize == 512){
 134                 ll_rw_block(opr,nbreq,bh);
 135         }else{
 136                 struct buffer_head *tmp[32];
 137                 int i;
 138                 for (i=0; i<nbreq; i++){
 139                         tmp[i] = bh[i]->b_next;
 140                 }
 141                 ll_rw_block(opr,nbreq,tmp);
 142         }
 143 }
 144 

/* [previous][next][first][last][top][bottom][index][help] */