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

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