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

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