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                                         brelse(*bhe);
 172                                         if (++bhe == &buflist[NBUF])
 173                                           bhe = buflist;
 174                                         left = 0;
 175                                         break;
 176                                 }
 177                         }                       
 178                         if (left < blocksize - offset)
 179                                 chars = left;
 180                         else
 181                                 chars = blocksize - offset;
 182                         filp->f_pos += chars;
 183                         left -= chars;
 184                         read += chars;
 185                         if (*bhe) {
 186                                 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 187                                 brelse(*bhe);
 188                                 buf += chars;
 189                         } else {
 190                                 while (chars-->0)
 191                                         put_fs_byte(0,buf++);
 192                         }
 193                         offset = 0;
 194                         if (++bhe == &buflist[NBUF])
 195                                 bhe = buflist;
 196                 } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
 197         } while (left > 0);
 198 
 199 /* Release the read-ahead blocks */
 200         while (bhe != bhb) {
 201                 brelse(*bhe);
 202                 if (++bhe == &buflist[NBUF])
 203                         bhe = buflist;
 204         };
 205         if (!read)
 206                 return -EIO;
 207         filp->f_reada = 1;
 208         return read;
 209 }
 210 
 211 int block_fsync(struct inode *inode, struct file *filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 212 {
 213         return fsync_dev (inode->i_rdev);
 214 }

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