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

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