4 * Copyright (C) 1992 Rick Sladkey
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.
12 * Expire cache on write to a file by Wai S Kok (Oct 1994).
14 * nfs regular file handling functions
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>
23 #include <linux/nfs_fs.h>
24 #include <linux/malloc.h>
26 #include <asm/segment.h>
27 #include <asm/system.h>
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
*);
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 */
41 NULL
, /* no special open is needed */
43 nfs_fsync
, /* fsync */
46 struct inode_operations nfs_file_inode_operations
= {
47 &nfs_file_operations
, /* default file operations */
58 NULL
, /* follow_link */
63 /* Once data is inserted, it can only be deleted, if (in_use==0). */
65 int in_use
; /* currently in use? */
66 unsigned long inode_num
; /* inode number */
67 off_t file_pos
; /* file position */
68 int len
; /* size of data */
69 unsigned long time
; /* time, this entry was inserted */
70 char * buf
; /* data */
71 int buf_size
; /* size of buffer */
74 #define READ_CACHE_SIZE 5
75 #define EXPIRE_CACHE (HZ * 3) /* keep no longer than 3 seconds */
77 unsigned long num_requests
= 0;
78 unsigned long num_cache_hits
= 0;
80 static int tail
= 0; /* next cache slot to replace */
82 static struct read_cache cache
[READ_CACHE_SIZE
] = {
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 { 0, 0, -1, 0, 0, NULL
, 0 },
87 { 0, 0, -1, 0, 0, NULL
, 0 } };
89 static int nfs_fsync(struct inode
*inode
, struct file
*file
)
94 static int nfs_file_read(struct inode
*inode
, struct file
*file
, char *buf
,
97 int result
, hunk
, i
, n
, fs
;
98 struct nfs_fattr fattr
;
103 printk("nfs_file_read: inode = NULL\n");
106 if (!S_ISREG(inode
->i_mode
)) {
107 printk("nfs_file_read: read from non-file, mode %07o\n",
112 if (pos
+ count
> inode
->i_size
)
113 count
= inode
->i_size
- pos
;
118 for (i
= 0; i
< READ_CACHE_SIZE
; i
++)
119 if ((cache
[i
].inode_num
== inode
->i_ino
)
120 && (cache
[i
].file_pos
<= pos
)
121 && (cache
[i
].file_pos
+ cache
[i
].len
>= pos
+ count
)
122 && (abs(jiffies
- cache
[i
].time
) < EXPIRE_CACHE
))
124 if (i
< READ_CACHE_SIZE
) {
128 memcpy_tofs(buf
, cache
[i
].buf
+ pos
- cache
[i
].file_pos
, count
);
130 file
->f_pos
+= count
;
134 n
= NFS_SERVER(inode
)->rsize
;
135 for (i
= 0; i
< count
- n
; i
+= n
) {
136 result
= nfs_proc_read(NFS_SERVER(inode
), NFS_FH(inode
),
137 pos
, n
, buf
, &fattr
, 1);
144 nfs_refresh_inode(inode
, &fattr
);
149 if (!(data
= (char *)kmalloc(n
, GFP_KERNEL
))) {
153 result
= nfs_proc_read(NFS_SERVER(inode
), NFS_FH(inode
),
154 pos
, n
, data
, &fattr
, fs
);
164 file
->f_pos
= pos
+ hunk
;
165 nfs_refresh_inode(inode
, &fattr
);
168 memcpy_tofs(buf
, data
, hunk
);
169 file
->f_pos
= pos
+ hunk
;
170 nfs_refresh_inode(inode
, &fattr
);
172 if (cache
[tail
].in_use
== 0) {
174 kfree_s(cache
[tail
].buf
, cache
[tail
].buf_size
);
175 cache
[tail
].buf
= data
;
176 cache
[tail
].buf_size
= n
;
177 cache
[tail
].inode_num
= inode
->i_ino
;
178 cache
[tail
].file_pos
= pos
;
179 cache
[tail
].len
= result
;
180 cache
[tail
].time
= jiffies
;
181 if (++tail
>= READ_CACHE_SIZE
)
189 static int nfs_file_write(struct inode
*inode
, struct file
*file
, const char *buf
,
192 int result
, hunk
, i
, n
, pos
;
193 struct nfs_fattr fattr
;
196 printk("nfs_file_write: inode = NULL\n");
199 if (!S_ISREG(inode
->i_mode
)) {
200 printk("nfs_file_write: write to non-file, mode %07o\n",
208 /* If hit, cache is dirty and must be expired. */
209 for (i
= 0; i
< READ_CACHE_SIZE
; i
++)
210 if(cache
[i
].inode_num
== inode
->i_ino
)
211 cache
[i
].time
-= EXPIRE_CACHE
;
215 if (file
->f_flags
& O_APPEND
)
217 n
= NFS_SERVER(inode
)->wsize
;
218 for (i
= 0; i
< count
; i
+= n
) {
222 result
= nfs_proc_write(NFS_SERVER(inode
), NFS_FH(inode
),
223 pos
, hunk
, buf
, &fattr
);
234 nfs_refresh_inode(inode
, &fattr
);