patch-1.3.67 linux/fs/nfs/file.c
Next file: linux/fs/nfs/inode.c
Previous file: linux/fs/nfs/Makefile
Back to the patch index
Back to the overall index
- Lines: 265
- Date:
Tue Feb 20 10:01:35 1996
- Orig file:
v1.3.66/linux/fs/nfs/file.c
- Orig date:
Sat Feb 17 16:02:53 1996
diff -u --recursive --new-file v1.3.66/linux/fs/nfs/file.c linux/fs/nfs/file.c
@@ -11,6 +11,8 @@
*
* Expire cache on write to a file by Wai S Kok (Oct 1994).
*
+ * Total rewrite of read side for new NFS buffer cache.. Linus.
+ *
* nfs regular file handling functions
*/
@@ -22,13 +24,16 @@
#include <linux/mm.h>
#include <linux/nfs_fs.h>
#include <linux/malloc.h>
+#include <linux/pagemap.h>
#include <asm/segment.h>
#include <asm/system.h>
+static int nfs_file_mmap(struct inode *, struct file *, struct vm_area_struct *);
static int nfs_file_read(struct inode *, struct file *, char *, int);
static int nfs_file_write(struct inode *, struct file *, const char *, int);
static int nfs_fsync(struct inode *, struct file *);
+static int nfs_readpage(struct inode * inode, struct page * page);
static struct file_operations nfs_file_operations = {
NULL, /* lseek - default */
@@ -37,7 +42,7 @@
NULL, /* readdir - bad */
NULL, /* select - default */
NULL, /* ioctl - default */
- nfs_mmap, /* mmap */
+ nfs_file_mmap, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
nfs_fsync, /* fsync */
@@ -56,136 +61,98 @@
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* readpage */
+ nfs_readpage, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
NULL /* truncate */
};
-/* Once data is inserted, it can only be deleted, if (in_use==0). */
-struct read_cache {
- int in_use; /* currently in use? */
- unsigned long inode_num; /* inode number */
- off_t file_pos; /* file position */
- int len; /* size of data */
- unsigned long time; /* time, this entry was inserted */
- char * buf; /* data */
- int buf_size; /* size of buffer */
-};
+static inline void revalidate_inode(struct nfs_server * server, struct inode * inode)
+{
+ struct nfs_fattr fattr;
-#define READ_CACHE_SIZE 5
-#define EXPIRE_CACHE (HZ * 3) /* keep no longer than 3 seconds */
+ if (jiffies - NFS_READTIME(inode) < server->acregmax)
+ return;
+
+ NFS_READTIME(inode) = jiffies;
+ if (nfs_proc_getattr(server, NFS_FH(inode), &fattr) == 0) {
+ nfs_refresh_inode(inode, &fattr);
+ if (fattr.mtime.seconds == NFS_OLDMTIME(inode))
+ return;
+ NFS_OLDMTIME(inode) = fattr.mtime.seconds;
+ }
+ invalidate_inode_pages(inode, 0);
+}
-unsigned long num_requests = 0;
-unsigned long num_cache_hits = 0;
-static int tail = 0; /* next cache slot to replace */
+static int nfs_file_read(struct inode * inode, struct file * file,
+ char * buf, int count)
+{
+ revalidate_inode(NFS_SERVER(inode), inode);
+ return generic_file_read(inode, file, buf, count);
+}
-static struct read_cache cache[READ_CACHE_SIZE] = {
- { 0, 0, -1, 0, 0, NULL, 0 },
- { 0, 0, -1, 0, 0, NULL, 0 },
- { 0, 0, -1, 0, 0, NULL, 0 },
- { 0, 0, -1, 0, 0, NULL, 0 },
- { 0, 0, -1, 0, 0, NULL, 0 } };
+static int nfs_file_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
+{
+ revalidate_inode(NFS_SERVER(inode), inode);
+ return generic_file_mmap(inode, file, vma);
+}
static int nfs_fsync(struct inode *inode, struct file *file)
{
return 0;
}
-static int nfs_file_read(struct inode *inode, struct file *file, char *buf,
- int count)
+static inline void do_read_nfs(struct inode * inode, char * buf, unsigned long pos)
{
- int result, hunk, i, n, fs;
+ int refresh = 0;
+ int count = PAGE_SIZE;
+ int rsize = NFS_SERVER(inode)->rsize;
struct nfs_fattr fattr;
- char *data;
- off_t pos;
- if (!inode) {
- printk("nfs_file_read: inode = NULL\n");
- return -EINVAL;
- }
- if (!S_ISREG(inode->i_mode)) {
- printk("nfs_file_read: read from non-file, mode %07o\n",
- inode->i_mode);
- return -EINVAL;
- }
- pos = file->f_pos;
- if (pos + count > inode->i_size)
- count = inode->i_size - pos;
- if (count <= 0)
- return 0;
- ++num_requests;
- cli();
- for (i = 0; i < READ_CACHE_SIZE; i++)
- if ((cache[i].inode_num == inode->i_ino)
- && (cache[i].file_pos <= pos)
- && (cache[i].file_pos + cache[i].len >= pos + count)
- && (jiffies - cache[i].time < EXPIRE_CACHE))
- break;
- if (i < READ_CACHE_SIZE) {
- ++cache[i].in_use;
- sti();
- ++num_cache_hits;
- memcpy_tofs(buf, cache[i].buf + pos - cache[i].file_pos, count);
- --cache[i].in_use;
- file->f_pos += count;
- return count;
- }
- sti();
- n = NFS_SERVER(inode)->rsize;
- for (i = 0; i < count - n; i += n) {
+ do {
+ int result;
+
+ if (count < rsize)
+ rsize = count;
result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
- pos, n, buf, &fattr, 1);
+ pos, rsize, buf, &fattr);
if (result < 0)
- return result;
- pos += result;
- buf += result;
- if (result < n) {
- file->f_pos = pos;
- nfs_refresh_inode(inode, &fattr);
- return i + result;
- }
- }
- fs = 0;
- if (!(data = (char *)kmalloc(n, GFP_KERNEL))) {
- data = buf;
- fs = 1;
- }
- result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
- pos, n, data, &fattr, fs);
- if (result < 0) {
- if (!fs)
- kfree_s(data, n);
- return result;
- }
- hunk = count - i;
- if (result < hunk)
- hunk = result;
- if (fs) {
- file->f_pos = pos + hunk;
+ goto partial;
+ refresh = 1;
+ count -= rsize;
+ pos += rsize;
+ buf += rsize;
+ if (result < rsize)
+ goto partial;
+ } while (count);
+ nfs_refresh_inode(inode, &fattr);
+ return;
+
+partial:
+ memset(buf, 0, count);
+ if (refresh)
nfs_refresh_inode(inode, &fattr);
- return i + hunk;
+}
+
+static int nfs_readpage(struct inode * inode, struct page * page)
+{
+ unsigned long address;
+
+ address = page_address(page);
+ page->count++;
+ wait_on_page(page);
+ if (page->uptodate) {
+ free_page(address);
+ return 0;
}
- memcpy_tofs(buf, data, hunk);
- file->f_pos = pos + hunk;
- nfs_refresh_inode(inode, &fattr);
- cli();
- if (cache[tail].in_use == 0) {
- if (cache[tail].buf)
- kfree_s(cache[tail].buf, cache[tail].buf_size);
- cache[tail].buf = data;
- cache[tail].buf_size = n;
- cache[tail].inode_num = inode->i_ino;
- cache[tail].file_pos = pos;
- cache[tail].len = result;
- cache[tail].time = jiffies;
- if (++tail >= READ_CACHE_SIZE)
- tail = 0;
- } else
- kfree_s(data, n);
- sti();
- return i + hunk;
+ page->locked = 1;
+ do_read_nfs(inode, (char *) address, page->offset);
+ page->locked = 0;
+ page->uptodate = 1;
+ wake_up(&page->wait);
+ free_page(address);
+ return 0;
}
static int nfs_file_write(struct inode *inode, struct file *file, const char *buf,
@@ -206,13 +173,6 @@
if (count <= 0)
return 0;
- cli();
- /* If hit, cache is dirty and must be expired. */
- for (i = 0; i < READ_CACHE_SIZE; i++)
- if(cache[i].inode_num == inode->i_ino)
- cache[i].time -= EXPIRE_CACHE;
- sti();
-
pos = file->f_pos;
if (file->f_flags & O_APPEND)
pos = inode->i_size;
@@ -221,7 +181,7 @@
hunk = count - i;
if (hunk >= n)
hunk = n;
- result = nfs_proc_write(NFS_SERVER(inode), NFS_FH(inode),
+ result = nfs_proc_write(inode,
pos, hunk, buf, &fattr);
if (result < 0)
return result;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this