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 #define NBUF 64
  18 
  19 int block_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  20 {
  21         int blocksize, blocksize_bits, i, j;
  22         int block, blocks;
  23         int offset;
  24         int chars;
  25         int written = 0;
  26         int cluster_list[4];
  27         struct buffer_head * bhlist[NBUF];
  28         int blocks_per_cluster;
  29         unsigned int size;
  30         unsigned int dev;
  31         struct buffer_head * bh;
  32         register char * p;
  33 
  34         dev = inode->i_rdev;
  35         if ( is_read_only( inode->i_rdev ))
  36                 return -EPERM;
  37         blocksize = BLOCK_SIZE;
  38         if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
  39                 blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
  40 
  41         i = blocksize;
  42         blocksize_bits = 0;
  43         while(i != 1) {
  44                 blocksize_bits++;
  45                 i >>= 1;
  46         }
  47 
  48         blocks_per_cluster = PAGE_SIZE / blocksize;
  49 
  50         block = filp->f_pos >> blocksize_bits;
  51         offset = filp->f_pos & (blocksize-1);
  52 
  53         if (blk_size[MAJOR(dev)])
  54                 size = (blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS) >> blocksize_bits;
  55         else
  56                 size = INT_MAX;
  57         while (count>0) {
  58                 if (block >= size)
  59                         return written;
  60                 chars = blocksize - offset;
  61                 if (chars > count)
  62                         chars=count;
  63 
  64 #if 0
  65                 if (chars == blocksize)
  66                         bh = getblk(dev, block, blocksize);
  67                 else
  68                         bh = breada(dev,block,block+1,block+2,-1);
  69 
  70 #else
  71                 for(i=0; i<blocks_per_cluster; i++) cluster_list[i] = block+i;
  72                 if((block % blocks_per_cluster) == 0)
  73                   generate_cluster(dev, cluster_list, blocksize);
  74                 bh = getblk(dev, block, blocksize);
  75 
  76                 if (chars != blocksize && !bh->b_uptodate) {
  77                   if(!filp->f_reada ||
  78                      !read_ahead[MAJOR(dev)]) {
  79                     /* We do this to force the read of a single buffer */
  80                     brelse(bh);
  81                     bh = bread(dev,block,blocksize);
  82                   } else {
  83                     /* Read-ahead before write */
  84                     blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9) / 2;
  85                     if (block + blocks > size) blocks = size - block;
  86                     if (blocks > NBUF) blocks=NBUF;
  87                     blocks -= (block % blocks_per_cluster);
  88                     if(!blocks) blocks = 1;
  89                     bhlist[0] = bh;
  90                     for(i=1; i<blocks; i++){
  91                       if(((i+block) % blocks_per_cluster) == 0) {
  92                         for(j=0; j<blocks_per_cluster; j++) cluster_list[j] = block+i+j;
  93                         generate_cluster(dev, cluster_list, blocksize);
  94                       };
  95                       bhlist[i] = getblk (dev, block+i, blocksize);
  96                       if(!bhlist[i]){
  97                         while(i >= 0) brelse(bhlist[i--]);
  98                         return written? written: -EIO;
  99                       };
 100                     };
 101                     ll_rw_block(READ, blocks, bhlist);
 102                     for(i=1; i<blocks; i++) brelse(bhlist[i]);
 103                       
 104                   };
 105                 };
 106 #endif
 107                 block++;
 108                 if (!bh)
 109                         return written?written:-EIO;
 110                 p = offset + bh->b_data;
 111                 offset = 0;
 112                 filp->f_pos += chars;
 113                 written += chars;
 114                 count -= chars;
 115                 memcpy_fromfs(p,buf,chars);
 116                 p += chars;
 117                 buf += chars;
 118                 bh->b_uptodate = 1;
 119                 mark_buffer_dirty(bh, 0);
 120                 brelse(bh);
 121         }
 122         filp->f_reada = 1;
 123         return written;
 124 }
 125 
 126 int block_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 127 {
 128         unsigned int block;
 129         unsigned int offset;
 130         int blocksize;
 131         int blocksize_bits, i;
 132         unsigned int blocks, rblocks, left;
 133         int bhrequest, uptodate;
 134         int cluster_list[4];
 135         int blocks_per_cluster;
 136         struct buffer_head ** bhb, ** bhe;
 137         struct buffer_head * buflist[NBUF];
 138         struct buffer_head * bhreq[NBUF];
 139         unsigned int chars;
 140         unsigned int size;
 141         unsigned int dev;
 142         int read;
 143 
 144         dev = inode->i_rdev;
 145         blocksize = BLOCK_SIZE;
 146         if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
 147                 blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
 148         i = blocksize;
 149         blocksize_bits = 0;
 150         while (i != 1) {
 151                 blocksize_bits++;
 152                 i >>= 1;
 153         }
 154 
 155         offset = filp->f_pos;
 156         if (blk_size[MAJOR(dev)])
 157                 size = blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
 158         else
 159                 size = INT_MAX;
 160 
 161         blocks_per_cluster = PAGE_SIZE / blocksize;
 162 
 163         if (offset > size)
 164                 left = 0;
 165         else
 166                 left = size - offset;
 167         if (left > count)
 168                 left = count;
 169         if (left <= 0)
 170                 return 0;
 171         read = 0;
 172         block = offset >> blocksize_bits;
 173         offset &= blocksize-1;
 174         size >>= blocksize_bits;
 175         rblocks = blocks = (left + offset + blocksize - 1) >> blocksize_bits;
 176         bhb = bhe = buflist;
 177         if (filp->f_reada) {
 178                 if (blocks < read_ahead[MAJOR(dev)] / (blocksize >> 9))
 179                         blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9);
 180                 blocks -= (block % blocks_per_cluster);
 181                 if (rblocks > blocks)
 182                         blocks = rblocks;
 183                 
 184         }
 185         if (block + blocks > size)
 186                 blocks = size - block;
 187 
 188         /* We do this in a two stage process.  We first try and request
 189            as many blocks as we can, then we wait for the first one to
 190            complete, and then we try and wrap up as many as are actually
 191            done.  This routine is rather generic, in that it can be used
 192            in a filesystem by substituting the appropriate function in
 193            for getblk.
 194 
 195            This routine is optimized to make maximum use of the various
 196            buffers and caches. */
 197 
 198         do {
 199                 bhrequest = 0;
 200                 uptodate = 1;
 201                 while (blocks) {
 202                         --blocks;
 203 #if 1
 204                         if((block % blocks_per_cluster) == 0) {
 205                           for(i=0; i<blocks_per_cluster; i++) cluster_list[i] = block+i;
 206                           generate_cluster(dev, cluster_list, blocksize);
 207                         }
 208 #endif
 209                         *bhb = getblk(dev, block++, blocksize);
 210                         if (*bhb && !(*bhb)->b_uptodate) {
 211                                 uptodate = 0;
 212                                 bhreq[bhrequest++] = *bhb;
 213                         }
 214 
 215                         if (++bhb == &buflist[NBUF])
 216                                 bhb = buflist;
 217 
 218                         /* If the block we have on hand is uptodate, go ahead
 219                            and complete processing. */
 220                         if (uptodate)
 221                                 break;
 222                         if (bhb == bhe)
 223                                 break;
 224                 }
 225 
 226                 /* Now request them all */
 227                 if (bhrequest) {
 228                         ll_rw_block(READ, bhrequest, bhreq);
 229                         refill_freelist(blocksize);
 230                 }
 231 
 232                 do { /* Finish off all I/O that has actually completed */
 233                         if (*bhe) {
 234                                 wait_on_buffer(*bhe);
 235                                 if (!(*bhe)->b_uptodate) {      /* read error? */
 236                                         brelse(*bhe);
 237                                         if (++bhe == &buflist[NBUF])
 238                                           bhe = buflist;
 239                                         left = 0;
 240                                         break;
 241                                 }
 242                         }                       
 243                         if (left < blocksize - offset)
 244                                 chars = left;
 245                         else
 246                                 chars = blocksize - offset;
 247                         filp->f_pos += chars;
 248                         left -= chars;
 249                         read += chars;
 250                         if (*bhe) {
 251                                 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 252                                 brelse(*bhe);
 253                                 buf += chars;
 254                         } else {
 255                                 while (chars-->0)
 256                                         put_fs_byte(0,buf++);
 257                         }
 258                         offset = 0;
 259                         if (++bhe == &buflist[NBUF])
 260                                 bhe = buflist;
 261                 } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
 262         } while (left > 0);
 263 
 264 /* Release the read-ahead blocks */
 265         while (bhe != bhb) {
 266                 brelse(*bhe);
 267                 if (++bhe == &buflist[NBUF])
 268                         bhe = buflist;
 269         };
 270         if (!read)
 271                 return -EIO;
 272         filp->f_reada = 1;
 273         return read;
 274 }
 275 
 276 int block_fsync(struct inode *inode, struct file *filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 277 {
 278         return fsync_dev (inode->i_rdev);
 279 }

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