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     NULL,                       /* mmap */
  46     NULL,                       /* no special open is needed */
  47     NULL,                       /* release */
  48     NULL                        /* 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     inode->i_atime = CURRENT_TIME;
 179     inode->i_dirt = 1;
 180 
 181     return read;
 182 }
 183 
 184 static int 
 185 xiafs_file_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187     off_t pos;
 188     int written, c;
 189     struct buffer_head * bh;
 190     char * cp;
 191 
 192     if (!inode) {
 193         printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
 194         return -EINVAL;
 195     }
 196     if (!S_ISREG(inode->i_mode)) {
 197         printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
 198         return -EINVAL;
 199     }
 200 /*
 201  * ok, append may not work when many processes are writing at the same time
 202  * but so what. That way leads to madness anyway.
 203  */
 204     if (filp->f_flags & O_APPEND)
 205         pos = inode->i_size;
 206     else
 207         pos = filp->f_pos;
 208     written = 0;
 209     while (written < count) {
 210         bh = xiafs_getblk(inode, pos >> XIAFS_ZSIZE_BITS(inode->i_sb), 1);
 211         if (!bh) {
 212             if (!written)
 213                 written = -ENOSPC;
 214             break;
 215         }
 216         c = XIAFS_ZSIZE(inode->i_sb) - (pos & (XIAFS_ZSIZE(inode->i_sb) - 1));
 217         if (c > count-written)
 218             c = count-written;
 219         if (c != XIAFS_ZSIZE(inode->i_sb) && !bh->b_uptodate) {
 220             ll_rw_block(READ, 1, &bh);
 221             wait_on_buffer(bh);
 222             if (!bh->b_uptodate) {
 223                 brelse(bh);
 224                 if (!written)
 225                     written = -EIO;
 226                 break;
 227             }
 228         }
 229         cp = (pos & (XIAFS_ZSIZE(inode->i_sb)-1)) + bh->b_data;
 230         pos += c;
 231         if (pos > inode->i_size) {
 232             inode->i_size = pos;
 233             inode->i_dirt = 1;
 234         }
 235         written += c;
 236         memcpy_fromfs(cp,buf,c);
 237         buf += c;
 238         bh->b_uptodate = 1;
 239         bh->b_dirt = 1;
 240         brelse(bh);
 241     }
 242     inode->i_mtime = CURRENT_TIME;
 243     filp->f_pos = pos;
 244     inode->i_dirt = 1;
 245 
 246     return written;
 247 }
 248 
 249 
 250 
 251 

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