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
  3. block_fsync

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

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