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 int block_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64         unsigned int block;
  65         unsigned int offset;
  66         int blocks, left;
  67         int bhrequest, uptodate;
  68         struct buffer_head ** bhb, ** bhe;
  69         struct buffer_head * buflist[NBUF];
  70         struct buffer_head * bhreq[NBUF];
  71         unsigned int chars;
  72         unsigned int size;
  73         unsigned int dev;
  74         int read;
  75 
  76         dev = inode->i_rdev;
  77         offset = filp->f_pos;
  78         if (blk_size[MAJOR(dev)])
  79                 size = blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
  80         else
  81                 size = 0x7fffffff;
  82 
  83         if (offset > size)
  84                 left = 0;
  85         else
  86                 left = size - offset;
  87         if (left > count)
  88                 left = count;
  89         if (left <= 0)
  90                 return 0;
  91         read = 0;
  92         block = offset >> BLOCK_SIZE_BITS;
  93         offset &= BLOCK_SIZE-1;
  94         size >>= BLOCK_SIZE_BITS;
  95         blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
  96         bhb = bhe = buflist;
  97         if (filp->f_reada) {
  98                 blocks += read_ahead[MAJOR(dev)] / (BLOCK_SIZE >> 9);
  99                 if (block + blocks > size)
 100                         blocks = size - block;
 101         }
 102 
 103         /* We do this in a two stage process.  We first try and request
 104            as many blocks as we can, then we wait for the first one to
 105            complete, and then we try and wrap up as many as are actually
 106            done.  This routine is rather generic, in that it can be used
 107            in a filesystem by substituting the appropriate function in
 108            for getblk.
 109 
 110            This routine is optimized to make maximum use of the various
 111            buffers and caches. */
 112 
 113         do {
 114                 bhrequest = 0;
 115                 uptodate = 1;
 116                 while (blocks) {
 117                         --blocks;
 118                         *bhb = getblk(dev, block++, BLOCK_SIZE);
 119                         if (*bhb && !(*bhb)->b_uptodate) {
 120                                 uptodate = 0;
 121                                 bhreq[bhrequest++] = *bhb;
 122                         }
 123 
 124                         if (++bhb == &buflist[NBUF])
 125                                 bhb = buflist;
 126 
 127                         /* If the block we have on hand is uptodate, go ahead
 128                            and complete processing. */
 129                         if (uptodate)
 130                                 break;
 131                         if (bhb == bhe)
 132                                 break;
 133                 }
 134 
 135                 /* Now request them all */
 136                 if (bhrequest)
 137                         ll_rw_block(READ, bhrequest, bhreq);
 138 
 139                 do { /* Finish off all I/O that has actually completed */
 140                         if (*bhe) {
 141                                 wait_on_buffer(*bhe);
 142                                 if (!(*bhe)->b_uptodate) {      /* read error? */
 143                                         left = 0;
 144                                         break;
 145                                 }
 146                         }                       
 147                         if (left < BLOCK_SIZE - offset)
 148                                 chars = left;
 149                         else
 150                                 chars = BLOCK_SIZE - offset;
 151                         filp->f_pos += chars;
 152                         left -= chars;
 153                         read += chars;
 154                         if (*bhe) {
 155                                 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 156                                 brelse(*bhe);
 157                                 buf += chars;
 158                         } else {
 159                                 while (chars-->0)
 160                                         put_fs_byte(0,buf++);
 161                         }
 162                         offset = 0;
 163                         if (++bhe == &buflist[NBUF])
 164                                 bhe = buflist;
 165                 } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
 166         } while (left > 0);
 167 
 168 /* Release the read-ahead blocks */
 169         while (bhe != bhb) {
 170                 brelse(*bhe);
 171                 if (++bhe == &buflist[NBUF])
 172                         bhe = buflist;
 173         };
 174         if (!read)
 175                 return -EIO;
 176         filp->f_reada = 1;
 177         return read;
 178 }

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