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

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