root/fs/block_dev.c

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

DEFINITIONS

This source file includes following definitions.
  1. block_write
  2. block_read

   1 /*
   2  *  linux/fs/block_dev.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #include <linux/errno.h>
   8 #include <linux/sched.h>
   9 #include <linux/kernel.h>
  10 #include <linux/locks.h>
  11 #include <asm/segment.h>
  12 #include <asm/system.h>
  13 
  14 extern int *blk_size[];
  15 
  16 int block_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  17 {
  18         int block = filp->f_pos >> BLOCK_SIZE_BITS;
  19         int offset = filp->f_pos & (BLOCK_SIZE-1);
  20         int chars;
  21         int written = 0;
  22         int size;
  23         unsigned int dev;
  24         struct buffer_head * bh;
  25         register char * p;
  26 
  27         dev = inode->i_rdev;
  28         if (blk_size[MAJOR(dev)])
  29                 size = blk_size[MAJOR(dev)][MINOR(dev)];
  30         else
  31                 size = 0x7fffffff;
  32         while (count>0) {
  33                 if (block >= size)
  34                         return written;
  35                 chars = BLOCK_SIZE - offset;
  36                 if (chars > count)
  37                         chars=count;
  38                 if (chars == BLOCK_SIZE)
  39                         bh = getblk(dev, block, BLOCK_SIZE);
  40                 else
  41                         bh = breada(dev,block,block+1,block+2,-1);
  42                 block++;
  43                 if (!bh)
  44                         return written?written:-EIO;
  45                 p = offset + bh->b_data;
  46                 offset = 0;
  47                 filp->f_pos += chars;
  48                 written += chars;
  49                 count -= chars;
  50                 memcpy_fromfs(p,buf,chars);
  51                 p += chars;
  52                 buf += chars;
  53                 bh->b_uptodate = 1;
  54                 bh->b_dirt = 1;
  55                 brelse(bh);
  56         }
  57         return written;
  58 }
  59 
  60 #define NBUF 16
  61 
  62 
  63 int block_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65         unsigned int block = filp->f_pos >> BLOCK_SIZE_BITS;
  66         unsigned int offset = filp->f_pos & (BLOCK_SIZE-1);
  67         int blocks, left;
  68         int bhrequest;
  69         int ra_blocks, max_block, nextblock;
  70         struct buffer_head ** bhb, ** bhe;
  71         struct buffer_head * buflist[NBUF];
  72         struct buffer_head * bhreq[NBUF];
  73         unsigned int chars;
  74         unsigned int size;
  75         unsigned int dev;
  76         int read = 0;
  77 
  78         dev = inode->i_rdev;
  79         if (blk_size[MAJOR(dev)])
  80                 size = blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
  81         else
  82                 size = 0x7fffffff;
  83 
  84         if (filp->f_pos > size)
  85                 left = 0;
  86         else
  87                 left = size - filp->f_pos;
  88         if (left > count)
  89                 left = count;
  90         if (left <= 0)
  91                 return 0;
  92 
  93         blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
  94         bhb = bhe = buflist;
  95         ra_blocks = read_ahead[MAJOR(dev)] / (BLOCK_SIZE >> 9);
  96         max_block = size;
  97         nextblock = -1;
  98 
  99         /* We do this in a two stage process.  We first try and request
 100            as many blocks as we can, then we wait for the first one to
 101            complete, and then we try and wrap up as many as are actually
 102            done.  This routine is rather generic, in that it can be used
 103            in a filesystem by substituting the appropriate function in
 104            for getblk.
 105 
 106            This routine is optimized to make maximum use of the various
 107            buffers and caches. */
 108 
 109         do {
 110                 bhrequest = 0;
 111                 while (blocks) {
 112                         int uptodate;
 113                         --blocks;
 114                         *bhb = getblk(dev, block++, BLOCK_SIZE);
 115                         uptodate = 1;
 116                         if (*bhb && !(*bhb)->b_uptodate) {
 117                                 uptodate = 0;
 118                                 bhreq[bhrequest++] = *bhb;
 119                                 nextblock = (*bhb)->b_blocknr + 1;
 120                               };
 121 
 122                         if (++bhb == &buflist[NBUF])
 123                                 bhb = buflist;
 124 
 125                         /* If the block we have on hand is uptodate, go ahead
 126                            and complete processing. */
 127                         if(bhrequest == 0 && uptodate) break;
 128 
 129                         if (bhb == bhe)
 130                                 break;
 131                       }
 132 
 133                 if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) { 
 134                   /* If we are going to read something anyways, add in the
 135                      read-ahead blocks */
 136                   while(ra_blocks){
 137                     if (block >= max_block) break;
 138                     if(bhrequest == NBUF) break;  /* Block full */
 139                     --ra_blocks;
 140                     *bhb = getblk(dev, block++, BLOCK_SIZE);
 141 
 142                     if (*bhb && !(*bhb)->b_uptodate) {
 143                       if((*bhb)->b_blocknr != nextblock) {
 144                         brelse(*bhb);
 145                         break;
 146                       };
 147                       nextblock = (*bhb)->b_blocknr + 1;
 148                       bhreq[bhrequest++] = *bhb;
 149                     };
 150                     
 151                     if (++bhb == &buflist[NBUF])
 152                       bhb = buflist;
 153                     
 154                     if (bhb == bhe)
 155                       break;
 156                   };
 157                 };
 158                 /* Now request them all */
 159                 if (bhrequest)
 160                   ll_rw_block(READ, bhrequest, bhreq);
 161 
 162                 do{ /* Finish off all I/O that has actually completed */
 163                   if (*bhe) {/* test for valid buffer */
 164                     wait_on_buffer(*bhe);
 165                     if (!(*bhe)->b_uptodate) {
 166                       do {
 167                         brelse(*bhe);
 168                         if (++bhe == &buflist[NBUF])
 169                           bhe = buflist;
 170                       } while (bhe != bhb);
 171                       break;
 172                     }
 173                   }
 174                   
 175                   if (left < BLOCK_SIZE - offset)
 176                     chars = left;
 177                   else
 178                     chars = BLOCK_SIZE - offset;
 179                   filp->f_pos += chars;
 180                   left -= chars;
 181                   read += chars;
 182                   if (*bhe) {
 183                     memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 184                     brelse(*bhe);
 185                     buf += chars;
 186                   } else {
 187                     while (chars-->0)
 188                       put_fs_byte(0,buf++);
 189                   }
 190                   offset = 0;
 191                   if (++bhe == &buflist[NBUF])
 192                     bhe = buflist;
 193                 } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) && 
 194                         (left > 0));
 195         } while (left > 0);
 196 
 197 /* Release the read-ahead blocks */
 198         while (bhe != bhb) {
 199           if (*bhe) brelse(*bhe);
 200           if (++bhe == &buflist[NBUF])
 201             bhe = buflist;
 202         };
 203 
 204         filp->f_reada = 1;
 205 
 206         if (!read)
 207                 return -EIO;
 208 
 209         return read;
 210 }

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