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

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