root/fs/nfs/file.c

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

DEFINITIONS

This source file includes following definitions.
  1. revalidate_inode
  2. nfs_file_read
  3. nfs_file_mmap
  4. nfs_fsync
  5. do_read_nfs
  6. nfs_readpage
  7. 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  *  Total rewrite of read side for new NFS buffer cache.. Linus.
  15  *
  16  *  nfs regular file handling functions
  17  */
  18 
  19 #include <linux/sched.h>
  20 #include <linux/kernel.h>
  21 #include <linux/errno.h>
  22 #include <linux/fcntl.h>
  23 #include <linux/stat.h>
  24 #include <linux/mm.h>
  25 #include <linux/nfs_fs.h>
  26 #include <linux/malloc.h>
  27 #include <linux/pagemap.h>
  28 
  29 #include <asm/segment.h>
  30 #include <asm/system.h>
  31 
  32 static int nfs_file_mmap(struct inode *, struct file *, struct vm_area_struct *);
  33 static int nfs_file_read(struct inode *, struct file *, char *, int);
  34 static int nfs_file_write(struct inode *, struct file *, const char *, int);
  35 static int nfs_fsync(struct inode *, struct file *);
  36 static int nfs_readpage(struct inode * inode, struct page * page);
  37 
  38 static struct file_operations nfs_file_operations = {
  39         NULL,                   /* lseek - default */
  40         nfs_file_read,          /* read */
  41         nfs_file_write,         /* write */
  42         NULL,                   /* readdir - bad */
  43         NULL,                   /* select - default */
  44         NULL,                   /* ioctl - default */
  45         nfs_file_mmap,          /* mmap */
  46         NULL,                   /* no special open is needed */
  47         NULL,                   /* release */
  48         nfs_fsync,              /* fsync */
  49 };
  50 
  51 struct inode_operations nfs_file_inode_operations = {
  52         &nfs_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         nfs_readpage,           /* readpage */
  65         NULL,                   /* writepage */
  66         NULL,                   /* bmap */
  67         NULL                    /* truncate */
  68 };
  69 
  70 static inline void revalidate_inode(struct nfs_server * server, struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         struct nfs_fattr fattr;
  73 
  74         if (jiffies - NFS_READTIME(inode) < server->acregmax)
  75                 return;
  76 
  77         NFS_READTIME(inode) = jiffies;
  78         if (nfs_proc_getattr(server, NFS_FH(inode), &fattr) == 0) {
  79                 nfs_refresh_inode(inode, &fattr);
  80                 if (fattr.mtime.seconds == NFS_OLDMTIME(inode))
  81                         return;
  82                 NFS_OLDMTIME(inode) = fattr.mtime.seconds;
  83         }
  84         invalidate_inode_pages(inode);
  85 }
  86 
  87 
  88 static int nfs_file_read(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
  89         char * buf, int count)
  90 {
  91         revalidate_inode(NFS_SERVER(inode), inode);
  92         return generic_file_read(inode, file, buf, count);
  93 }
  94 
  95 static int nfs_file_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         revalidate_inode(NFS_SERVER(inode), inode);
  98         return generic_file_mmap(inode, file, vma);
  99 }
 100 
 101 static int nfs_fsync(struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103         return 0;
 104 }
 105 
 106 static inline int do_read_nfs(struct inode * inode, struct page * page,
     /* [previous][next][first][last][top][bottom][index][help] */
 107         char * buf, unsigned long pos)
 108 {
 109         int result, refresh = 0;
 110         int count = PAGE_SIZE;
 111         int rsize = NFS_SERVER(inode)->rsize;
 112         struct nfs_fattr fattr;
 113 
 114         page->locked = 1;
 115         do {
 116                 if (count < rsize)
 117                         rsize = count;
 118                 result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), 
 119                         pos, rsize, buf, &fattr);
 120                 if (result < 0)
 121                         break;
 122                 refresh = 1;
 123                 count -= result;
 124                 pos += result;
 125                 buf += result;
 126                 if (result < rsize)
 127                         break;
 128         } while (count);
 129 
 130         memset(buf, 0, count);
 131         if (refresh) {
 132                 nfs_refresh_inode(inode, &fattr);
 133                 result = 0;
 134                 page->uptodate = 1;
 135         }
 136         page->locked = 0;
 137         wake_up(&page->wait);
 138         return result;
 139 }
 140 
 141 static int nfs_readpage(struct inode * inode, struct page * page)
     /* [previous][next][first][last][top][bottom][index][help] */
 142 {
 143         int error;
 144         unsigned long address;
 145 
 146         address = page_address(page);
 147         page->count++;
 148         error = do_read_nfs(inode, page, (char *) address, page->offset);
 149         free_page(address);
 150         return error;
 151 }
 152 
 153 static int nfs_file_write(struct inode *inode, struct file *file, const char *buf,
     /* [previous][next][first][last][top][bottom][index][help] */
 154                           int count)
 155 {
 156         int result, written, wsize;
 157         struct nfs_fattr fattr;
 158         unsigned long pos;
 159 
 160         if (!inode) {
 161                 printk("nfs_file_write: inode = NULL\n");
 162                 return -EINVAL;
 163         }
 164         if (!S_ISREG(inode->i_mode)) {
 165                 printk("nfs_file_write: write to non-file, mode %07o\n",
 166                         inode->i_mode);
 167                 return -EINVAL;
 168         }
 169         if (count <= 0)
 170                 return 0;
 171 
 172         pos = file->f_pos;
 173         if (file->f_flags & O_APPEND)
 174                 pos = inode->i_size;
 175         wsize = NFS_SERVER(inode)->wsize;
 176         result = 0;
 177         written = 0;
 178         while (written < count) {
 179                 int hunk = count - written;
 180                 if (hunk >= wsize)
 181                         hunk = wsize;
 182                 result = nfs_proc_write(inode,
 183                         pos, hunk, buf, &fattr);
 184                 if (result < 0)
 185                         break;
 186                 pos += hunk;
 187                 buf += hunk;
 188                 written += hunk;
 189                 if (hunk < wsize)
 190                         break;
 191         }
 192         if (!written)
 193                 return result;
 194         file->f_pos = pos;
 195         if (pos > inode->i_size)
 196                 inode->i_size = pos;
 197         nfs_refresh_inode(inode, &fattr);
 198         return written;
 199 }
 200 

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