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