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

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