home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / msdos / buffer.c next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  3.4 KB  |  149 lines

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