root/fs/nfs/file.c

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

DEFINITIONS

This source file includes following definitions.
  1. nfs_fsync
  2. nfs_file_read
  3. nfs_file_write

   1 /*
   2  *  linux/fs/nfs/file.c
   3  *
   4  *  Copyright (C) 1992  Rick Sladkey
   5  *
   6  *  Changes Copyright (C) 1994 by Florian La Roche
   7  *   - Do not copy data too often around in the kernel.
   8  *   - In nfs_file_read the return value of kmalloc wasn't checked.
   9  *   - Put in a better version of read look-ahead buffering. Original idea
  10  *     and implementation by Wai S Kok elekokws@ee.nus.sg.
  11  *
  12  *  Expire cache on write to a file by Wai S Kok (Oct 1994).
  13  *
  14  *  nfs regular file handling functions
  15  */
  16 
  17 #ifdef MODULE
  18 #include <linux/module.h>
  19 #endif
  20 
  21 #include <asm/segment.h>
  22 #include <asm/system.h>
  23 
  24 #include <linux/sched.h>
  25 #include <linux/kernel.h>
  26 #include <linux/errno.h>
  27 #include <linux/fcntl.h>
  28 #include <linux/stat.h>
  29 #include <linux/mm.h>
  30 #include <linux/nfs_fs.h>
  31 #include <linux/malloc.h>
  32 
  33 static int nfs_file_read(struct inode *, struct file *, char *, int);
  34 static int nfs_file_write(struct inode *, struct file *, char *, int);
  35 static int nfs_fsync(struct inode *, struct file *);
  36 
  37 static struct file_operations nfs_file_operations = {
  38         NULL,                   /* lseek - default */
  39         nfs_file_read,          /* read */
  40         nfs_file_write,         /* write */
  41         NULL,                   /* readdir - bad */
  42         NULL,                   /* select - default */
  43         NULL,                   /* ioctl - default */
  44         nfs_mmap,               /* mmap */
  45         NULL,                   /* no special open is needed */
  46         NULL,                   /* release */
  47         nfs_fsync,              /* fsync */
  48 };
  49 
  50 struct inode_operations nfs_file_inode_operations = {
  51         &nfs_file_operations,   /* default file operations */
  52         NULL,                   /* create */
  53         NULL,                   /* lookup */
  54         NULL,                   /* link */
  55         NULL,                   /* unlink */
  56         NULL,                   /* symlink */
  57         NULL,                   /* mkdir */
  58         NULL,                   /* rmdir */
  59         NULL,                   /* mknod */
  60         NULL,                   /* rename */
  61         NULL,                   /* readlink */
  62         NULL,                   /* follow_link */
  63         NULL,                   /* bmap */
  64         NULL                    /* truncate */
  65 };
  66 
  67 /* Once data is inserted, it can only be deleted, if (in_use==0). */
  68 struct read_cache {
  69         int             in_use;         /* currently in use? */
  70         unsigned long   inode_num;      /* inode number */
  71         off_t           file_pos;       /* file position */
  72         int             len;            /* size of data */
  73         unsigned long   time;           /* time, this entry was inserted */
  74         char *          buf;            /* data */
  75         int             buf_size;       /* size of buffer */
  76 };
  77 
  78 #define READ_CACHE_SIZE 5
  79 #define EXPIRE_CACHE (HZ * 3)           /* keep no longer than 3 seconds */
  80 
  81 unsigned long num_requests = 0;
  82 unsigned long num_cache_hits = 0;
  83 
  84 static int tail = 0;    /* next cache slot to replace */
  85 
  86 static struct read_cache cache[READ_CACHE_SIZE] = {
  87         { 0, 0, -1, 0, 0, NULL, 0 },
  88         { 0, 0, -1, 0, 0, NULL, 0 },
  89         { 0, 0, -1, 0, 0, NULL, 0 },
  90         { 0, 0, -1, 0, 0, NULL, 0 },
  91         { 0, 0, -1, 0, 0, NULL, 0 } };
  92 
  93 static int nfs_fsync(struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  94 {
  95         return 0;
  96 }
  97 
  98 static int nfs_file_read(struct inode *inode, struct file *file, char *buf,
     /* [previous][next][first][last][top][bottom][index][help] */
  99                          int count)
 100 {
 101         int result, hunk, i, n, fs;
 102         struct nfs_fattr fattr;
 103         char *data;
 104         off_t pos;
 105 
 106         if (!inode) {
 107                 printk("nfs_file_read: inode = NULL\n");
 108                 return -EINVAL;
 109         }
 110         if (!S_ISREG(inode->i_mode)) {
 111                 printk("nfs_file_read: read from non-file, mode %07o\n",
 112                         inode->i_mode);
 113                 return -EINVAL;
 114         }
 115         pos = file->f_pos;
 116         if (pos + count > inode->i_size)
 117                 count = inode->i_size - pos;
 118         if (count <= 0)
 119                 return 0;
 120         ++num_requests;
 121         cli();
 122         for (i = 0; i < READ_CACHE_SIZE; i++)
 123                 if ((cache[i].inode_num == inode->i_ino)
 124                         && (cache[i].file_pos <= pos)
 125                         && (cache[i].file_pos + cache[i].len >= pos + count)
 126                         && (abs(jiffies - cache[i].time) <= EXPIRE_CACHE))
 127                         break;
 128         if (i < READ_CACHE_SIZE) {
 129                 ++cache[i].in_use;
 130                 sti();
 131                 ++num_cache_hits;
 132                 memcpy_tofs(buf, cache[i].buf + pos - cache[i].file_pos, count);
 133                 --cache[i].in_use;
 134                 file->f_pos += count;
 135                 return count;
 136         }
 137         sti();
 138         n = NFS_SERVER(inode)->rsize;
 139         for (i = 0; i < count - n; i += n) {
 140                 result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), 
 141                         pos, n, buf, &fattr, 1);
 142                 if (result < 0)
 143                         return result;
 144                 pos += result;
 145                 buf += result;
 146                 if (result < n) {
 147                         file->f_pos = pos;
 148                         nfs_refresh_inode(inode, &fattr);
 149                         return i + result;
 150                 }
 151         }
 152         fs = 0;
 153         if (!(data = (char *)kmalloc(n, GFP_KERNEL))) {
 154                 data = buf;
 155                 fs = 1;
 156         }
 157         result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
 158                 pos, n, data, &fattr, fs);
 159         if (result < 0) {
 160                 if (!fs)
 161                         kfree_s(data, n);
 162                 return result;
 163         }
 164         hunk = count - i;
 165         if (result < hunk)
 166                 hunk = result;
 167         if (fs) {
 168                 file->f_pos = pos + hunk;
 169                 nfs_refresh_inode(inode, &fattr);
 170                 return i + hunk;
 171         }
 172         memcpy_tofs(buf, data, hunk);
 173         file->f_pos = pos + hunk;
 174         nfs_refresh_inode(inode, &fattr);
 175         cli();
 176         if (cache[tail].in_use == 0) {
 177                 if (cache[tail].buf)
 178                         kfree_s(cache[tail].buf, cache[tail].buf_size);
 179                 cache[tail].buf = data;
 180                 cache[tail].buf_size = n;
 181                 cache[tail].inode_num = inode->i_ino;
 182                 cache[tail].file_pos = pos;
 183                 cache[tail].len = result;
 184                 cache[tail].time = jiffies;
 185                 if (++tail >= READ_CACHE_SIZE)
 186                         tail = 0;
 187         } else
 188                 kfree_s(data, n);
 189         sti();
 190         return i + hunk;
 191 }
 192 
 193 static int nfs_file_write(struct inode *inode, struct file *file, char *buf,
     /* [previous][next][first][last][top][bottom][index][help] */
 194                           int count)
 195 {
 196         int result, hunk, i, n, pos;
 197         struct nfs_fattr fattr;
 198 
 199         if (!inode) {
 200                 printk("nfs_file_write: inode = NULL\n");
 201                 return -EINVAL;
 202         }
 203         if (!S_ISREG(inode->i_mode)) {
 204                 printk("nfs_file_write: write to non-file, mode %07o\n",
 205                         inode->i_mode);
 206                 return -EINVAL;
 207         }
 208         if (count <= 0)
 209                 return 0;
 210 
 211         cli();
 212         /* If hit, cache is dirty and must be expired. */
 213         for (i = 0; i < READ_CACHE_SIZE; i++)
 214                 if(cache[i].inode_num == inode->i_ino)
 215                         cache[i].time -= EXPIRE_CACHE;
 216         sti();
 217 
 218         pos = file->f_pos;
 219         if (file->f_flags & O_APPEND)
 220                 pos = inode->i_size;
 221         n = NFS_SERVER(inode)->wsize;
 222         for (i = 0; i < count; i += n) {
 223                 hunk = count - i;
 224                 if (hunk >= n)
 225                         hunk = n;
 226                 result = nfs_proc_write(NFS_SERVER(inode), NFS_FH(inode), 
 227                         pos, hunk, buf, &fattr);
 228                 if (result < 0)
 229                         return result;
 230                 pos += hunk;
 231                 buf += hunk;
 232                 if (hunk < n) {
 233                         i += hunk;
 234                         break;
 235                 }
 236         }
 237         file->f_pos = pos;
 238         nfs_refresh_inode(inode, &fattr);
 239         return i;
 240 }
 241 

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