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         if(zones < read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb)))
 101           zones = read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb));
 102         if (zone_nr + zones > f_zones)
 103             zones = f_zones - zone_nr;
 104     }
 105 
 106     /* We do this in a two stage process.  We first try and request
 107        as many blocks as we can, then we wait for the first one to
 108        complete, and then we try and wrap up as many as are actually
 109        done.  This routine is rather generic, in that it can be used
 110        in a filesystem by substituting the appropriate function in
 111        for getblk.
 112        
 113        This routine is optimized to make maximum use of the various
 114        buffers and caches. */
 115 
 116     do {
 117         bhrequest = 0;
 118         uptodate = 1;
 119         while (zones--) {
 120             *bhb = xiafs_getblk(inode, zone_nr++, 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                     brelse(*bhe);
 146                     if (++bhe == &buflist[NBUF])
 147                       bhe = buflist;
 148                     left = 0;
 149                     break;
 150                 }
 151             }
 152             if (left < XIAFS_ZSIZE(inode->i_sb) - offset)
 153                 chars = left;
 154             else
 155                 chars = XIAFS_ZSIZE(inode->i_sb) - offset;
 156             filp->f_pos += chars;
 157             left -= chars;
 158             read += chars;
 159             if (*bhe) {
 160                 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 161                 brelse(*bhe);
 162                 buf += chars;
 163             } else {
 164                 while (chars-->0)
 165                     put_fs_byte(0,buf++);
 166             }
 167             offset = 0;
 168             if (++bhe == &buflist[NBUF])
 169                 bhe = buflist;
 170         } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
 171     } while (left > 0);
 172 
 173 /* Release the read-ahead blocks */
 174     while (bhe != bhb) {
 175         brelse(*bhe);
 176         if (++bhe == &buflist[NBUF])
 177             bhe = buflist;
 178     };
 179     if (!read)
 180         return -EIO;
 181     filp->f_reada = 1;
 182     if (!IS_RDONLY (inode)) {
 183         inode->i_atime = CURRENT_TIME;
 184         inode->i_dirt = 1;
 185     }
 186     return read;
 187 }
 188 
 189 static int 
 190 xiafs_file_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192     off_t pos;
 193     int written, c;
 194     struct buffer_head * bh;
 195     char * cp;
 196 
 197     if (!inode) {
 198         printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
 199         return -EINVAL;
 200     }
 201     if (!S_ISREG(inode->i_mode)) {
 202         printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
 203         return -EINVAL;
 204     }
 205 /*
 206  * ok, append may not work when many processes are writing at the same time
 207  * but so what. That way leads to madness anyway.
 208  */
 209     if (filp->f_flags & O_APPEND)
 210         pos = inode->i_size;
 211     else
 212         pos = filp->f_pos;
 213     written = 0;
 214     while (written < count) {
 215         bh = xiafs_getblk(inode, pos >> XIAFS_ZSIZE_BITS(inode->i_sb), 1);
 216         if (!bh) {
 217             if (!written)
 218                 written = -ENOSPC;
 219             break;
 220         }
 221         c = XIAFS_ZSIZE(inode->i_sb) - (pos & (XIAFS_ZSIZE(inode->i_sb) - 1));
 222         if (c > count-written)
 223             c = count-written;
 224         if (c != XIAFS_ZSIZE(inode->i_sb) && !bh->b_uptodate) {
 225             ll_rw_block(READ, 1, &bh);
 226             wait_on_buffer(bh);
 227             if (!bh->b_uptodate) {
 228                 brelse(bh);
 229                 if (!written)
 230                     written = -EIO;
 231                 break;
 232             }
 233         }
 234         cp = (pos & (XIAFS_ZSIZE(inode->i_sb)-1)) + bh->b_data;
 235         pos += c;
 236         if (pos > inode->i_size) {
 237             inode->i_size = pos;
 238             inode->i_dirt = 1;
 239         }
 240         written += c;
 241         memcpy_fromfs(cp,buf,c);
 242         buf += c;
 243         bh->b_uptodate = 1;
 244         mark_buffer_dirty(bh, 0);
 245         brelse(bh);
 246     }
 247     inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 248     filp->f_pos = pos;
 249     inode->i_dirt = 1;
 250 
 251     return written;
 252 }

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