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 
  21 #include <asm/segment.h>
  22 #include <asm/system.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 *, const 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_file_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     generic_readpage,           /* readpage */
  65     NULL,                       /* writepage */
  66     xiafs_bmap,                 /* bmap */
  67     xiafs_truncate,             /* truncate */
  68     NULL                        /* permission */
  69 };
  70 
  71 static int 
  72 xiafs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74     int read, left, chars;
  75     int zone_nr, zones, f_zones, offset;
  76     int bhrequest, uptodate;
  77     struct buffer_head ** bhb, ** bhe;
  78     struct buffer_head * bhreq[NBUF];
  79     struct buffer_head * buflist[NBUF];
  80 
  81     if (!inode) {
  82         printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
  83         return -EINVAL;
  84     }
  85     if (!S_ISREG(inode->i_mode)) {
  86         printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
  87         return -EINVAL;
  88     }
  89     offset = filp->f_pos;
  90     left = inode->i_size - offset;
  91     if (left > count)
  92         left = count;
  93     if (left <= 0)
  94         return 0;
  95     read = 0;
  96     zone_nr = offset >> XIAFS_ZSIZE_BITS(inode->i_sb);
  97     offset &= XIAFS_ZSIZE(inode->i_sb) -1 ;
  98     f_zones =(inode->i_size+XIAFS_ZSIZE(inode->i_sb)-1)>>XIAFS_ZSIZE_BITS(inode->i_sb);
  99     zones = (left+offset+XIAFS_ZSIZE(inode->i_sb)-1) >> XIAFS_ZSIZE_BITS(inode->i_sb);
 100     bhb = bhe = buflist;
 101     if (filp->f_reada) {
 102         if(zones < read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb)))
 103           zones = read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb));
 104         if (zone_nr + zones > f_zones)
 105             zones = f_zones - zone_nr;
 106     }
 107 
 108     /* We do this in a two stage process.  We first try and request
 109        as many blocks as we can, then we wait for the first one to
 110        complete, and then we try and wrap up as many as are actually
 111        done.  This routine is rather generic, in that it can be used
 112        in a filesystem by substituting the appropriate function in
 113        for getblk.
 114        
 115        This routine is optimized to make maximum use of the various
 116        buffers and caches. */
 117 
 118     do {
 119         bhrequest = 0;
 120         uptodate = 1;
 121         while (zones--) {
 122             *bhb = xiafs_getblk(inode, zone_nr++, 0);
 123             if (*bhb && !buffer_uptodate(*bhb)) {
 124                 uptodate = 0;
 125                 bhreq[bhrequest++] = *bhb;
 126             }
 127 
 128             if (++bhb == &buflist[NBUF])
 129                 bhb = buflist;
 130             
 131             /* If the block we have on hand is uptodate, go ahead
 132                and complete processing. */
 133             if (uptodate)
 134                 break;
 135             if (bhb == bhe)
 136                 break;
 137         }
 138 
 139         /* Now request them all */
 140         if (bhrequest)
 141             ll_rw_block(READ, bhrequest, bhreq);
 142 
 143         do { /* Finish off all I/O that has actually completed */
 144             if (*bhe) {
 145                 wait_on_buffer(*bhe);
 146                 if (!buffer_uptodate(*bhe)) {   /* read error? */
 147                     brelse(*bhe);
 148                     if (++bhe == &buflist[NBUF])
 149                       bhe = buflist;
 150                     left = 0;
 151                     break;
 152                 }
 153             }
 154             if (left < XIAFS_ZSIZE(inode->i_sb) - offset)
 155                 chars = left;
 156             else
 157                 chars = XIAFS_ZSIZE(inode->i_sb) - offset;
 158             filp->f_pos += chars;
 159             left -= chars;
 160             read += chars;
 161             if (*bhe) {
 162                 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 163                 brelse(*bhe);
 164                 buf += chars;
 165             } else {
 166                 while (chars-->0)
 167                     put_user(0,buf++);
 168             }
 169             offset = 0;
 170             if (++bhe == &buflist[NBUF])
 171                 bhe = buflist;
 172         } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
 173     } while (left > 0);
 174 
 175 /* Release the read-ahead blocks */
 176     while (bhe != bhb) {
 177         brelse(*bhe);
 178         if (++bhe == &buflist[NBUF])
 179             bhe = buflist;
 180     };
 181     if (!read)
 182         return -EIO;
 183     filp->f_reada = 1;
 184     if (!IS_RDONLY (inode)) {
 185         inode->i_atime = CURRENT_TIME;
 186         inode->i_dirt = 1;
 187     }
 188     return read;
 189 }
 190 
 191 static int 
 192 xiafs_file_write(struct inode * inode, struct file * filp, const char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 193 {
 194     off_t pos;
 195     int written, c;
 196     struct buffer_head * bh;
 197     char * cp;
 198 
 199     if (!inode) {
 200         printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
 201         return -EINVAL;
 202     }
 203     if (!S_ISREG(inode->i_mode)) {
 204         printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
 205         return -EINVAL;
 206     }
 207 /*
 208  * ok, append may not work when many processes are writing at the same time
 209  * but so what. That way leads to madness anyway.
 210  */
 211     if (filp->f_flags & O_APPEND)
 212         pos = inode->i_size;
 213     else
 214         pos = filp->f_pos;
 215     written = 0;
 216     while (written < count) {
 217         bh = xiafs_getblk(inode, pos >> XIAFS_ZSIZE_BITS(inode->i_sb), 1);
 218         if (!bh) {
 219             if (!written)
 220                 written = -ENOSPC;
 221             break;
 222         }
 223         c = XIAFS_ZSIZE(inode->i_sb) - (pos & (XIAFS_ZSIZE(inode->i_sb) - 1));
 224         if (c > count-written)
 225             c = count-written;
 226         if (c != XIAFS_ZSIZE(inode->i_sb) && !buffer_uptodate(bh)) {
 227             ll_rw_block(READ, 1, &bh);
 228             wait_on_buffer(bh);
 229             if (!buffer_uptodate(bh)) {
 230                 brelse(bh);
 231                 if (!written)
 232                     written = -EIO;
 233                 break;
 234             }
 235         }
 236         cp = (pos & (XIAFS_ZSIZE(inode->i_sb)-1)) + bh->b_data;
 237         pos += c;
 238         if (pos > inode->i_size) {
 239             inode->i_size = pos;
 240             inode->i_dirt = 1;
 241         }
 242         written += c;
 243         memcpy_fromfs(cp,buf,c);
 244         buf += c;
 245         mark_buffer_uptodate(bh, 1);
 246         mark_buffer_dirty(bh, 0);
 247         brelse(bh);
 248     }
 249     inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 250     filp->f_pos = pos;
 251     inode->i_dirt = 1;
 252 
 253     return written;
 254 }

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