root/fs/minix/file.c

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

DEFINITIONS

This source file includes following definitions.
  1. minix_file_read
  2. minix_file_write

   1 /*
   2  *  linux/fs/minix/file.c
   3  *
   4  *  Copyright (C) 1991, 1992 Linus Torvalds
   5  *
   6  *  minix regular file handling primitives
   7  */
   8 
   9 #include <asm/segment.h>
  10 #include <asm/system.h>
  11 
  12 #include <linux/sched.h>
  13 #include <linux/minix_fs.h>
  14 #include <linux/kernel.h>
  15 #include <linux/errno.h>
  16 #include <linux/fcntl.h>
  17 #include <linux/stat.h>
  18 #include <linux/locks.h>
  19 
  20 #define NBUF    16
  21 
  22 #define MIN(a,b) (((a)<(b))?(a):(b))
  23 #define MAX(a,b) (((a)>(b))?(a):(b))
  24 
  25 #include <linux/fs.h>
  26 #include <linux/minix_fs.h>
  27 
  28 static int minix_file_read(struct inode *, struct file *, char *, int);
  29 static int minix_file_write(struct inode *, struct file *, char *, int);
  30 
  31 /*
  32  * We have mostly NULL's here: the current defaults are ok for
  33  * the minix filesystem.
  34  */
  35 static struct file_operations minix_file_operations = {
  36         NULL,                   /* lseek - default */
  37         minix_file_read,        /* read */
  38         minix_file_write,       /* write */
  39         NULL,                   /* readdir - bad */
  40         NULL,                   /* select - default */
  41         NULL,                   /* ioctl - default */
  42         NULL,                   /* mmap */
  43         NULL,                   /* no special open is needed */
  44         NULL                    /* release */
  45 };
  46 
  47 struct inode_operations minix_file_inode_operations = {
  48         &minix_file_operations, /* default file operations */
  49         NULL,                   /* create */
  50         NULL,                   /* lookup */
  51         NULL,                   /* link */
  52         NULL,                   /* unlink */
  53         NULL,                   /* symlink */
  54         NULL,                   /* mkdir */
  55         NULL,                   /* rmdir */
  56         NULL,                   /* mknod */
  57         NULL,                   /* rename */
  58         NULL,                   /* readlink */
  59         NULL,                   /* follow_link */
  60         minix_bmap,             /* bmap */
  61         minix_truncate,         /* truncate */
  62         NULL                    /* permission */
  63 };
  64 
  65 static int minix_file_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67         int read,left,chars;
  68         int block, blocks, offset;
  69         int bhrequest, uptodate;
  70         struct buffer_head ** bhb, ** bhe;
  71         struct buffer_head * bhreq[NBUF];
  72         struct buffer_head * buflist[NBUF];
  73         unsigned int size;
  74 
  75         if (!inode) {
  76                 printk("minix_file_read: inode = NULL\n");
  77                 return -EINVAL;
  78         }
  79         if (!S_ISREG(inode->i_mode)) {
  80                 printk("minix_file_read: mode = %07o\n",inode->i_mode);
  81                 return -EINVAL;
  82         }
  83         offset = filp->f_pos;
  84         size = inode->i_size;
  85         if (offset > size)
  86                 left = 0;
  87         else
  88                 left = size - offset;
  89         if (left > count)
  90                 left = count;
  91         if (left <= 0)
  92                 return 0;
  93         read = 0;
  94         block = offset >> BLOCK_SIZE_BITS;
  95         offset &= BLOCK_SIZE-1;
  96         size = (size + (BLOCK_SIZE-1)) >> BLOCK_SIZE_BITS;
  97         blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
  98         bhb = bhe = buflist;
  99         if (filp->f_reada) {
 100                 blocks += read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
 101                 if (block + blocks > size)
 102                         blocks = size - block;
 103         }
 104 
 105         /* We do this in a two stage process.  We first try and request
 106            as many blocks as we can, then we wait for the first one to
 107            complete, and then we try and wrap up as many as are actually
 108            done.  This routine is rather generic, in that it can be used
 109            in a filesystem by substituting the appropriate function in
 110            for getblk.
 111 
 112            This routine is optimized to make maximum use of the various
 113            buffers and caches. */
 114 
 115         do {
 116                 bhrequest = 0;
 117                 uptodate = 1;
 118                 while (blocks) {
 119                         --blocks;
 120                         *bhb = minix_getblk(inode, block++, 0);
 121                         if (*bhb && !(*bhb)->b_uptodate) {
 122                                 uptodate = 0;
 123                                 bhreq[bhrequest++] = *bhb;
 124                         }
 125 
 126                         if (++bhb == &buflist[NBUF])
 127                                 bhb = buflist;
 128 
 129                         /* If the block we have on hand is uptodate, go ahead
 130                            and complete processing. */
 131                         if (uptodate)
 132                                 break;
 133                         if (bhb == bhe)
 134                                 break;
 135                 }
 136 
 137                 /* Now request them all */
 138                 if (bhrequest)
 139                         ll_rw_block(READ, bhrequest, bhreq);
 140 
 141                 do { /* Finish off all I/O that has actually completed */
 142                         if (*bhe) {
 143                                 wait_on_buffer(*bhe);
 144                                 if (!(*bhe)->b_uptodate) {      /* read error? */
 145                                         left = 0;
 146                                         break;
 147                                 }
 148                         }
 149                         if (left < BLOCK_SIZE - offset)
 150                                 chars = left;
 151                         else
 152                                 chars = BLOCK_SIZE - offset;
 153                         filp->f_pos += chars;
 154                         left -= chars;
 155                         read += chars;
 156                         if (*bhe) {
 157                                 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 158                                 brelse(*bhe);
 159                                 buf += chars;
 160                         } else {
 161                                 while (chars-->0)
 162                                         put_fs_byte(0,buf++);
 163                         }
 164                         offset = 0;
 165                         if (++bhe == &buflist[NBUF])
 166                                 bhe = buflist;
 167                 } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
 168         } while (left > 0);
 169 
 170 /* Release the read-ahead blocks */
 171         while (bhe != bhb) {
 172                 brelse(*bhe);
 173                 if (++bhe == &buflist[NBUF])
 174                         bhe = buflist;
 175         };
 176         if (!read)
 177                 return -EIO;
 178         filp->f_reada = 1;
 179         if (!IS_RDONLY(inode)) {
 180                 inode->i_atime = CURRENT_TIME;
 181                 inode->i_dirt = 1;
 182         }
 183         return read;
 184 }
 185 
 186 static int minix_file_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188         off_t pos;
 189         int written,c;
 190         struct buffer_head * bh;
 191         char * p;
 192 
 193         if (!inode) {
 194                 printk("minix_file_write: inode = NULL\n");
 195                 return -EINVAL;
 196         }
 197         if (!S_ISREG(inode->i_mode)) {
 198                 printk("minix_file_write: mode = %07o\n",inode->i_mode);
 199                 return -EINVAL;
 200         }
 201 /*
 202  * ok, append may not work when many processes are writing at the same time
 203  * but so what. That way leads to madness anyway.
 204  */
 205         if (filp->f_flags & O_APPEND)
 206                 pos = inode->i_size;
 207         else
 208                 pos = filp->f_pos;
 209         written = 0;
 210         while (written<count) {
 211                 bh = minix_getblk(inode,pos/BLOCK_SIZE,1);
 212                 if (!bh) {
 213                         if (!written)
 214                                 written = -ENOSPC;
 215                         break;
 216                 }
 217                 c = BLOCK_SIZE - (pos % BLOCK_SIZE);
 218                 if (c > count-written)
 219                         c = count-written;
 220                 if (c != BLOCK_SIZE && !bh->b_uptodate) {
 221                         ll_rw_block(READ, 1, &bh);
 222                         wait_on_buffer(bh);
 223                         if (!bh->b_uptodate) {
 224                                 brelse(bh);
 225                                 if (!written)
 226                                         written = -EIO;
 227                                 break;
 228                         }
 229                 }
 230                 p = (pos % BLOCK_SIZE) + bh->b_data;
 231                 pos += c;
 232                 if (pos > inode->i_size) {
 233                         inode->i_size = pos;
 234                         inode->i_dirt = 1;
 235                 }
 236                 written += c;
 237                 memcpy_fromfs(p,buf,c);
 238                 buf += c;
 239                 bh->b_uptodate = 1;
 240                 bh->b_dirt = 1;
 241                 brelse(bh);
 242         }
 243         inode->i_mtime = CURRENT_TIME;
 244         inode->i_ctime = CURRENT_TIME;
 245         filp->f_pos = pos;
 246         inode->i_dirt = 1;
 247         return written;
 248 }

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