This source file includes following definitions.
- nfs_fsync
- nfs_file_read
- nfs_file_write
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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,
35 nfs_file_read,
36 nfs_file_write,
37 NULL,
38 NULL,
39 NULL,
40 nfs_mmap,
41 NULL,
42 NULL,
43 nfs_fsync,
44 };
45
46 struct inode_operations nfs_file_inode_operations = {
47 &nfs_file_operations,
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 NULL,
53 NULL,
54 NULL,
55 NULL,
56 NULL,
57 NULL,
58 NULL,
59 NULL,
60 NULL,
61 NULL,
62 NULL
63 };
64
65
66 struct read_cache {
67 int in_use;
68 unsigned long inode_num;
69 off_t file_pos;
70 int len;
71 unsigned long time;
72 char * buf;
73 int buf_size;
74 };
75
76 #define READ_CACHE_SIZE 5
77 #define EXPIRE_CACHE (HZ * 3)
78
79 unsigned long num_requests = 0;
80 unsigned long num_cache_hits = 0;
81
82 static int tail = 0;
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)
92 {
93 return 0;
94 }
95
96 static int nfs_file_read(struct inode *inode, struct file *file, char *buf,
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,
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
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