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         unsigned 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 32
  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         unsigned int left;
  85         unsigned int blocks;
  86         int bhrequest, uptodate;
  87         struct buffer_head ** bhb, ** bhe;
  88         struct buffer_head * buflist[NBUF];
  89         struct buffer_head * bhreq[NBUF];
  90         unsigned int chars;
  91         unsigned int size;
  92         unsigned int dev;
  93         int read;
  94 
  95         dev = inode->i_rdev;
  96         blocksize = BLOCK_SIZE;
  97         if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
  98                 blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
  99         i = blocksize;
 100         blocksize_bits = 0;
 101         while (i != 1) {
 102                 blocksize_bits++;
 103                 i >>= 1;
 104         }
 105 
 106         offset = filp->f_pos;
 107         if (blk_size[MAJOR(dev)])
 108                 size = blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
 109         else
 110                 size = INT_MAX;
 111 
 112         if (offset > size)
 113                 left = 0;
 114         else
 115                 left = size - offset;
 116         if (left > count)
 117                 left = count;
 118         if (left <= 0)
 119                 return 0;
 120         read = 0;
 121         block = offset >> blocksize_bits;
 122         offset &= blocksize-1;
 123         size >>= blocksize_bits;
 124         blocks = (left + offset + blocksize - 1) >> blocksize_bits;
 125         bhb = bhe = buflist;
 126         if (filp->f_reada) {
 127                 blocks += read_ahead[MAJOR(dev)] / (blocksize >> 9);
 128                 if (block + blocks > size)
 129                         blocks = size - block;
 130         }
 131 
 132         /* We do this in a two stage process.  We first try and request
 133            as many blocks as we can, then we wait for the first one to
 134            complete, and then we try and wrap up as many as are actually
 135            done.  This routine is rather generic, in that it can be used
 136            in a filesystem by substituting the appropriate function in
 137            for getblk.
 138 
 139            This routine is optimized to make maximum use of the various
 140            buffers and caches. */
 141 
 142         do {
 143                 bhrequest = 0;
 144                 uptodate = 1;
 145                 while (blocks) {
 146                         --blocks;
 147                         *bhb = getblk(dev, block++, blocksize);
 148                         if (*bhb && !(*bhb)->b_uptodate) {
 149                                 uptodate = 0;
 150                                 bhreq[bhrequest++] = *bhb;
 151                         }
 152 
 153                         if (++bhb == &buflist[NBUF])
 154                                 bhb = buflist;
 155 
 156                         /* If the block we have on hand is uptodate, go ahead
 157                            and complete processing. */
 158                         if (uptodate)
 159                                 break;
 160                         if (bhb == bhe)
 161                                 break;
 162                 }
 163 
 164                 /* Now request them all */
 165                 if (bhrequest)
 166                         ll_rw_block(READ, bhrequest, bhreq);
 167 
 168                 do { /* Finish off all I/O that has actually completed */
 169                         if (*bhe) {
 170                                 wait_on_buffer(*bhe);
 171                                 if (!(*bhe)->b_uptodate) {      /* read error? */
 172                                         brelse(*bhe);
 173                                         if (++bhe == &buflist[NBUF])
 174                                           bhe = buflist;
 175                                         left = 0;
 176                                         break;
 177                                 }
 178                         }                       
 179                         if (left < blocksize - offset)
 180                                 chars = left;
 181                         else
 182                                 chars = blocksize - offset;
 183                         filp->f_pos += chars;
 184                         left -= chars;
 185                         read += chars;
 186                         if (*bhe) {
 187                                 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 188                                 brelse(*bhe);
 189                                 buf += chars;
 190                         } else {
 191                                 while (chars-->0)
 192                                         put_fs_byte(0,buf++);
 193                         }
 194                         offset = 0;
 195                         if (++bhe == &buflist[NBUF])
 196                                 bhe = buflist;
 197                 } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
 198         } while (left > 0);
 199 
 200 /* Release the read-ahead blocks */
 201         while (bhe != bhb) {
 202                 brelse(*bhe);
 203                 if (++bhe == &buflist[NBUF])
 204                         bhe = buflist;
 205         };
 206         if (!read)
 207                 return -EIO;
 208         filp->f_reada = 1;
 209         return read;
 210 }
 211 
 212 int block_fsync(struct inode *inode, struct file *filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 213 {
 214         return fsync_dev (inode->i_rdev);
 215 }

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