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    16
  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                     left = 0;
 145                     break;
 146                 }
 147             }
 148             if (left < XIAFS_ZSIZE(inode->i_sb) - offset)
 149                 chars = left;
 150             else
 151                 chars = XIAFS_ZSIZE(inode->i_sb) - offset;
 152             filp->f_pos += chars;
 153             left -= chars;
 154             read += chars;
 155             if (*bhe) {
 156                 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 157                 brelse(*bhe);
 158                 buf += chars;
 159             } else {
 160                 while (chars-->0)
 161                     put_fs_byte(0,buf++);
 162             }
 163             offset = 0;
 164             if (++bhe == &buflist[NBUF])
 165                 bhe = buflist;
 166         } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
 167     } while (left > 0);
 168 
 169 /* Release the read-ahead blocks */
 170     while (bhe != bhb) {
 171         brelse(*bhe);
 172         if (++bhe == &buflist[NBUF])
 173             bhe = buflist;
 174     };
 175     if (!read)
 176         return -EIO;
 177     filp->f_reada = 1;
 178     if (!IS_RDONLY (inode)) {
 179         inode->i_atime = CURRENT_TIME;
 180         inode->i_dirt = 1;
 181     }
 182     return read;
 183 }
 184 
 185 static int 
 186 xiafs_file_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188     off_t pos;
 189     int written, c;
 190     struct buffer_head * bh;
 191     char * cp;
 192 
 193     if (!inode) {
 194         printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
 195         return -EINVAL;
 196     }
 197     if (!S_ISREG(inode->i_mode)) {
 198         printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
 199         return -EINVAL;
 200     }
 201 /*
 202  * ok, append may not work when many processes are writing at the same time
 203  * but so what. That way leads to madness anyway.
 204  */
 205     if (filp->f_flags & O_APPEND)
 206         pos = inode->i_size;
 207     else
 208         pos = filp->f_pos;
 209     written = 0;
 210     while (written < count) {
 211         bh = xiafs_getblk(inode, pos >> XIAFS_ZSIZE_BITS(inode->i_sb), 1);
 212         if (!bh) {
 213             if (!written)
 214                 written = -ENOSPC;
 215             break;
 216         }
 217         c = XIAFS_ZSIZE(inode->i_sb) - (pos & (XIAFS_ZSIZE(inode->i_sb) - 1));
 218         if (c > count-written)
 219             c = count-written;
 220         if (c != XIAFS_ZSIZE(inode->i_sb) && !bh->b_uptodate) {
 221             ll_rw_block(READ, 1, &bh);
 222             wait_on_buffer(bh);
 223             if (!bh->b_uptodate) {
 224                 brelse(bh);
 225                 if (!written)
 226                     written = -EIO;
 227                 break;
 228             }
 229         }
 230         cp = (pos & (XIAFS_ZSIZE(inode->i_sb)-1)) + bh->b_data;
 231         pos += c;
 232         if (pos > inode->i_size) {
 233             inode->i_size = pos;
 234             inode->i_dirt = 1;
 235         }
 236         written += c;
 237         memcpy_fromfs(cp,buf,c);
 238         buf += c;
 239         bh->b_uptodate = 1;
 240         bh->b_dirt = 1;
 241         brelse(bh);
 242     }
 243     inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 244     filp->f_pos = pos;
 245     inode->i_dirt = 1;
 246 
 247     return written;
 248 }
 249 
 250 
 251 
 252 

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