root/fs/xiafs/file.c

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

DEFINITIONS

This source file includes following definitions.
  1. xiafs_file_read
  2. xiafs_file_write

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

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