root/fs/ext/file.c

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

DEFINITIONS

This source file includes following definitions.
  1. ext_file_read
  2. ext_file_write

   1 /*
   2  *  linux/fs/ext/file.c
   3  *
   4  *  Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
   5  *
   6  *  from
   7  *
   8  *  linux/fs/minix/file.c
   9  *
  10  *  Copyright (C) 1991, 1992 Linus Torvalds
  11  *
  12  *  ext regular file handling primitives
  13  */
  14 
  15 #include <asm/segment.h>
  16 #include <asm/system.h>
  17 
  18 #include <linux/sched.h>
  19 #include <linux/ext_fs.h>
  20 #include <linux/kernel.h>
  21 #include <linux/errno.h>
  22 #include <linux/fcntl.h>
  23 #include <linux/stat.h>
  24 #include <linux/locks.h>
  25 
  26 #define NBUF    16
  27 
  28 #define MIN(a,b) (((a)<(b))?(a):(b))
  29 #define MAX(a,b) (((a)>(b))?(a):(b))
  30 
  31 #include <linux/fs.h>
  32 #include <linux/ext_fs.h>
  33 
  34 static int ext_file_read(struct inode *, struct file *, char *, int);
  35 static int ext_file_write(struct inode *, struct file *, char *, int);
  36 
  37 /*
  38  * We have mostly NULL's here: the current defaults are ok for
  39  * the ext filesystem.
  40  */
  41 static struct file_operations ext_file_operations = {
  42         NULL,                   /* lseek - default */
  43         ext_file_read,  /* read */
  44         ext_file_write, /* write */
  45         NULL,                   /* readdir - bad */
  46         NULL,                   /* select - default */
  47         NULL,                   /* ioctl - default */
  48         NULL,                   /* mmap */
  49         NULL,                   /* no special open is needed */
  50         NULL                    /* release */
  51 };
  52 
  53 struct inode_operations ext_file_inode_operations = {
  54         &ext_file_operations,   /* default file operations */
  55         NULL,                   /* create */
  56         NULL,                   /* lookup */
  57         NULL,                   /* link */
  58         NULL,                   /* unlink */
  59         NULL,                   /* symlink */
  60         NULL,                   /* mkdir */
  61         NULL,                   /* rmdir */
  62         NULL,                   /* mknod */
  63         NULL,                   /* rename */
  64         NULL,                   /* readlink */
  65         NULL,                   /* follow_link */
  66         ext_bmap,               /* bmap */
  67         ext_truncate            /* truncate */
  68 };
  69 
  70 static int ext_file_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         int read,left,chars;
  73         int block, blocks, offset;
  74         struct buffer_head ** bhb, ** bhe;
  75         struct buffer_head * buflist[NBUF];
  76 
  77         if (!inode) {
  78                 printk("ext_file_read: inode = NULL\n");
  79                 return -EINVAL;
  80         }
  81         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
  82                 printk("ext_file_read: mode = %07o\n",inode->i_mode);
  83                 return -EINVAL;
  84         }
  85         if (filp->f_pos > inode->i_size)
  86                 left = 0;
  87         else
  88                 left = inode->i_size - filp->f_pos;
  89         if (left > count)
  90                 left = count;
  91         if (left <= 0)
  92                 return 0;
  93         read = 0;
  94         block = filp->f_pos >> BLOCK_SIZE_BITS;
  95         offset = filp->f_pos & (BLOCK_SIZE-1);
  96         blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
  97         bhb = bhe = buflist;
  98         do {
  99                 if (blocks) {
 100                         --blocks;
 101                         *bhb = ext_getblk(inode,block++,0);
 102                         if (*bhb && !(*bhb)->b_uptodate)
 103                                 ll_rw_block(READ,*bhb);
 104 
 105                         if (++bhb == &buflist[NBUF])
 106                                 bhb = buflist;
 107 
 108                         if (bhb != bhe)
 109                                 continue;
 110                 }
 111                 if (*bhe) {
 112                         wait_on_buffer(*bhe);
 113                         if (!(*bhe)->b_uptodate) {
 114                                 do {
 115                                         brelse(*bhe);
 116                                         if (++bhe == &buflist[NBUF])
 117                                                 bhe = buflist;
 118                                 } while (bhe != bhb);
 119                                 break;
 120                         }
 121                 }
 122 
 123                 if (left < BLOCK_SIZE - offset)
 124                         chars = left;
 125                 else
 126                         chars = BLOCK_SIZE - offset;
 127                 filp->f_pos += chars;
 128                 left -= chars;
 129                 read += chars;
 130                 if (*bhe) {
 131                         memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 132                         brelse(*bhe);
 133                         buf += chars;
 134                 } else {
 135                         while (chars-->0)
 136                                 put_fs_byte(0,buf++);
 137                 }
 138                 offset = 0;
 139                 if (++bhe == &buflist[NBUF])
 140                         bhe = buflist;
 141         } while (left > 0);
 142         if (!read)
 143                 return -EIO;
 144         if (!IS_RDONLY(inode)) {
 145                 inode->i_atime = CURRENT_TIME;
 146                 inode->i_dirt = 1;
 147         }
 148         return read;
 149 }
 150 
 151 static int ext_file_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 152 {
 153         off_t pos;
 154         int written,c;
 155         struct buffer_head * bh;
 156         char * p;
 157 
 158         if (!inode) {
 159                 printk("ext_file_write: inode = NULL\n");
 160                 return -EINVAL;
 161         }
 162         if (!S_ISREG(inode->i_mode)) {
 163                 printk("ext_file_write: mode = %07o\n",inode->i_mode);
 164                 return -EINVAL;
 165         }
 166 /*
 167  * ok, append may not work when many processes are writing at the same time
 168  * but so what. That way leads to madness anyway.
 169  */
 170         if (filp->f_flags & O_APPEND)
 171                 pos = inode->i_size;
 172         else
 173                 pos = filp->f_pos;
 174         written = 0;
 175         while (written<count) {
 176                 bh = ext_getblk(inode,pos/BLOCK_SIZE,1);
 177                 if (!bh) {
 178                         if (!written)
 179                                 written = -ENOSPC;
 180                         break;
 181                 }
 182                 c = BLOCK_SIZE - (pos % BLOCK_SIZE);
 183                 if (c > count-written)
 184                         c = count-written;
 185                 if (c != BLOCK_SIZE && !bh->b_uptodate) {
 186                         ll_rw_block(READ,bh);
 187                         wait_on_buffer(bh);
 188                         if (!bh->b_uptodate) {
 189                                 brelse(bh);
 190                                 if (!written)
 191                                         written = -EIO;
 192                                 break;
 193                         }
 194                 }
 195                 p = (pos % BLOCK_SIZE) + bh->b_data;
 196                 pos += c;
 197                 if (pos > inode->i_size) {
 198                         inode->i_size = pos;
 199                         inode->i_dirt = 1;
 200                 }
 201                 written += c;
 202                 memcpy_fromfs(p,buf,c);
 203                 buf += c;
 204                 bh->b_uptodate = 1;
 205                 bh->b_dirt = 1;
 206                 brelse(bh);
 207         }
 208         inode->i_mtime = CURRENT_TIME;
 209         inode->i_ctime = CURRENT_TIME;
 210         filp->f_pos = pos;
 211         inode->i_dirt = 1;
 212         return written;
 213 }

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