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

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