This source file includes following definitions.
- nfs_dir_read
- nfs_readdir
- nfs_lookup_cache_index
- nfs_lookup_cache_lookup
- nfs_lookup_cache_add
- nfs_lookup_cache_remove
- nfs_lookup_cache_refresh
- nfs_lookup
- nfs_create
- nfs_mknod
- nfs_mkdir
- nfs_rmdir
- nfs_unlink
- nfs_symlink
- nfs_link
- nfs_rename
- nfs_refresh_inode
1
2
3
4
5
6
7
8
9 #include <linux/sched.h>
10 #include <linux/errno.h>
11 #include <linux/stat.h>
12 #include <linux/nfs_fs.h>
13 #include <linux/fcntl.h>
14 #include <linux/string.h>
15 #include <linux/kernel.h>
16 #include <linux/mm.h>
17
18 #include <asm/segment.h>
19
20 static int nfs_dir_read(struct inode *, struct file *filp, char *buf,
21 int count);
22 static int nfs_readdir(struct inode *, struct file *, struct dirent *, int);
23 static int nfs_lookup(struct inode *dir, const char *name, int len,
24 struct inode **result);
25 static int nfs_create(struct inode *dir, const char *name, int len, int mode,
26 struct inode **result);
27 static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode);
28 static int nfs_rmdir(struct inode *dir, const char *name, int len);
29 static int nfs_unlink(struct inode *dir, const char *name, int len);
30 static int nfs_symlink(struct inode *inode, const char *name, int len,
31 const char *symname);
32 static int nfs_link(struct inode *oldinode, struct inode *dir,
33 const char *name, int len);
34 static int nfs_mknod(struct inode *dir, const char *name, int len, int mode,
35 int rdev);
36 static int nfs_rename(struct inode *old_dir, const char *old_name,
37 int old_len, struct inode *new_dir, const char *new_name,
38 int new_len);
39
40 static struct file_operations nfs_dir_operations = {
41 NULL,
42 nfs_dir_read,
43 NULL,
44 nfs_readdir,
45 NULL,
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 NULL
51 };
52
53 struct inode_operations nfs_dir_inode_operations = {
54 &nfs_dir_operations,
55 nfs_create,
56 nfs_lookup,
57 nfs_link,
58 nfs_unlink,
59 nfs_symlink,
60 nfs_mkdir,
61 nfs_rmdir,
62 nfs_mknod,
63 nfs_rename,
64 NULL,
65 NULL,
66 NULL,
67 NULL,
68 NULL
69 };
70
71 static int nfs_dir_read(struct inode *inode, struct file *filp, char *buf,
72 int count)
73 {
74 return -EISDIR;
75 }
76
77
78
79
80
81
82
83
84
85 static int nfs_readdir(struct inode *inode, struct file *filp,
86 struct dirent *dirent, int count)
87 {
88 static int c_dev = 0;
89 static int c_ino;
90 static int c_size;
91 static struct nfs_entry *c_entry = NULL;
92
93 int result;
94 int i;
95 struct nfs_entry *entry;
96
97 if (!inode || !S_ISDIR(inode->i_mode)) {
98 printk("nfs_readdir: inode is NULL or not a directory\n");
99 return -EBADF;
100 }
101
102
103
104 if (c_entry == NULL) {
105 i = sizeof (struct nfs_entry)*NFS_READDIR_CACHE_SIZE;
106 c_entry = (struct nfs_entry *) kmalloc(i, GFP_KERNEL);
107 for (i = 0; i < NFS_READDIR_CACHE_SIZE; i++) {
108 c_entry[i].name = (char *) kmalloc(NFS_MAXNAMLEN + 1,
109 GFP_KERNEL);
110 }
111 }
112 entry = NULL;
113
114
115
116 if (inode->i_dev == c_dev && inode->i_ino == c_ino) {
117 for (i = 0; i < c_size; i++) {
118 if (filp->f_pos == c_entry[i].cookie) {
119 if (i == c_size - 1) {
120 if (c_entry[i].eof)
121 return 0;
122 }
123 else
124 entry = c_entry + i + 1;
125 break;
126 }
127 }
128 }
129
130
131
132 if (!entry) {
133 result = nfs_proc_readdir(NFS_SERVER(inode), NFS_FH(inode),
134 filp->f_pos, NFS_READDIR_CACHE_SIZE, c_entry);
135 if (result < 0) {
136 c_dev = 0;
137 return result;
138 }
139 if (result > 0) {
140 c_dev = inode->i_dev;
141 c_ino = inode->i_ino;
142 c_size = result;
143 entry = c_entry + 0;
144 }
145 }
146
147
148
149 if (entry) {
150 i = strlen(entry->name);
151 memcpy_tofs(dirent->d_name, entry->name, i + 1);
152 put_fs_long(entry->fileid, &dirent->d_ino);
153 put_fs_word(i, &dirent->d_reclen);
154 filp->f_pos = entry->cookie;
155 return i;
156 }
157 return 0;
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 static struct nfs_lookup_cache_entry {
174 int dev;
175 int inode;
176 char filename[NFS_MAXNAMLEN + 1];
177 struct nfs_fh fhandle;
178 struct nfs_fattr fattr;
179 int expiration_date;
180 } nfs_lookup_cache[NFS_LOOKUP_CACHE_SIZE];
181
182 static struct nfs_lookup_cache_entry *nfs_lookup_cache_index(struct inode *dir,
183 const char *filename)
184 {
185 struct nfs_lookup_cache_entry *entry;
186 int i;
187
188 for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
189 entry = nfs_lookup_cache + i;
190 if (entry->dev == dir->i_dev && entry->inode == dir->i_ino
191 && !strncmp(filename, entry->filename, NFS_MAXNAMLEN))
192 return entry;
193 }
194 return NULL;
195 }
196
197 static int nfs_lookup_cache_lookup(struct inode *dir, const char *filename,
198 struct nfs_fh *fhandle,
199 struct nfs_fattr *fattr)
200 {
201 static int nfs_lookup_cache_in_use = 0;
202
203 struct nfs_lookup_cache_entry *entry;
204
205 if (!nfs_lookup_cache_in_use) {
206 memset(nfs_lookup_cache, 0, sizeof(nfs_lookup_cache));
207 nfs_lookup_cache_in_use = 1;
208 }
209 if ((entry = nfs_lookup_cache_index(dir, filename))) {
210 if (jiffies > entry->expiration_date) {
211 entry->dev = 0;
212 return 0;
213 }
214 *fhandle = entry->fhandle;
215 *fattr = entry->fattr;
216 return 1;
217 }
218 return 0;
219 }
220
221 static void nfs_lookup_cache_add(struct inode *dir, const char *filename,
222 struct nfs_fh *fhandle,
223 struct nfs_fattr *fattr)
224 {
225 static int nfs_lookup_cache_pos = 0;
226 struct nfs_lookup_cache_entry *entry;
227
228
229 if (fattr->size == -1 || fattr->uid == -1 || fattr->gid == -1
230 || fattr->atime.seconds == -1 || fattr->mtime.seconds == -1)
231 return;
232 if (!(entry = nfs_lookup_cache_index(dir, filename))) {
233 entry = nfs_lookup_cache + nfs_lookup_cache_pos++;
234 if (nfs_lookup_cache_pos == NFS_LOOKUP_CACHE_SIZE)
235 nfs_lookup_cache_pos = 0;
236 }
237 entry->dev = dir->i_dev;
238 entry->inode = dir->i_ino;
239 strcpy(entry->filename, filename);
240 entry->fhandle = *fhandle;
241 entry->fattr = *fattr;
242 entry->expiration_date = jiffies + (S_ISDIR(fattr->mode)
243 ? NFS_SERVER(dir)->acdirmax : NFS_SERVER(dir)->acregmax);
244 }
245
246 static void nfs_lookup_cache_remove(struct inode *dir, struct inode *inode,
247 const char *filename)
248 {
249 struct nfs_lookup_cache_entry *entry;
250 int dev;
251 int fileid;
252 int i;
253
254 if (inode) {
255 dev = inode->i_dev;
256 fileid = inode->i_ino;
257 }
258 else if ((entry = nfs_lookup_cache_index(dir, filename))) {
259 dev = entry->dev;
260 fileid = entry->fattr.fileid;
261 }
262 else
263 return;
264 for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
265 entry = nfs_lookup_cache + i;
266 if (entry->dev == dev && entry->fattr.fileid == fileid)
267 entry->dev = 0;
268 }
269 }
270
271 static void nfs_lookup_cache_refresh(struct inode *file,
272 struct nfs_fattr *fattr)
273 {
274 struct nfs_lookup_cache_entry *entry;
275 int dev = file->i_dev;
276 int fileid = file->i_ino;
277 int i;
278
279 for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
280 entry = nfs_lookup_cache + i;
281 if (entry->dev == dev && entry->fattr.fileid == fileid)
282 entry->fattr = *fattr;
283 }
284 }
285
286 static int nfs_lookup(struct inode *dir, const char *name, int len,
287 struct inode **result)
288 {
289 struct nfs_fh fhandle;
290 struct nfs_fattr fattr;
291 int error;
292
293 *result = NULL;
294 if (!dir || !S_ISDIR(dir->i_mode)) {
295 printk("nfs_lookup: inode is NULL or not a directory\n");
296 iput(dir);
297 return -ENOENT;
298 }
299 if (len > NFS_MAXNAMLEN) {
300 iput(dir);
301 return -ENAMETOOLONG;
302 }
303 if (len == 1 && name[0] == '.') {
304 *result = dir;
305 return 0;
306 }
307 if ((NFS_SERVER(dir)->flags & NFS_MOUNT_NOAC)
308 || !nfs_lookup_cache_lookup(dir, name, &fhandle, &fattr)) {
309 if ((error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir),
310 name, &fhandle, &fattr))) {
311 iput(dir);
312 return error;
313 }
314 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
315 }
316 if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) {
317 iput(dir);
318 return -EACCES;
319 }
320 iput(dir);
321 return 0;
322 }
323
324 static int nfs_create(struct inode *dir, const char *name, int len, int mode,
325 struct inode **result)
326 {
327 struct nfs_sattr sattr;
328 struct nfs_fattr fattr;
329 struct nfs_fh fhandle;
330 int error;
331
332 *result = NULL;
333 if (!dir || !S_ISDIR(dir->i_mode)) {
334 printk("nfs_create: inode is NULL or not a directory\n");
335 iput(dir);
336 return -ENOENT;
337 }
338 if (len > NFS_MAXNAMLEN) {
339 iput(dir);
340 return -ENAMETOOLONG;
341 }
342 sattr.mode = mode;
343 sattr.uid = sattr.gid = sattr.size = -1;
344 sattr.atime.seconds = sattr.mtime.seconds = -1;
345 if ((error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
346 name, &sattr, &fhandle, &fattr))) {
347 iput(dir);
348 return error;
349 }
350 if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) {
351 iput(dir);
352 return -EACCES;
353 }
354 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
355 iput(dir);
356 return 0;
357 }
358
359 static int nfs_mknod(struct inode *dir, const char *name, int len,
360 int mode, int rdev)
361 {
362 struct nfs_sattr sattr;
363 struct nfs_fattr fattr;
364 struct nfs_fh fhandle;
365 int error;
366
367 if (!dir || !S_ISDIR(dir->i_mode)) {
368 printk("nfs_mknod: inode is NULL or not a directory\n");
369 iput(dir);
370 return -ENOENT;
371 }
372 if (len > NFS_MAXNAMLEN) {
373 iput(dir);
374 return -ENAMETOOLONG;
375 }
376 sattr.mode = mode;
377 sattr.uid = sattr.gid = -1;
378 if (S_ISCHR(mode) || S_ISBLK(mode))
379 sattr.size = rdev;
380 else
381 sattr.size = -1;
382 sattr.atime.seconds = sattr.mtime.seconds = -1;
383 error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
384 name, &sattr, &fhandle, &fattr);
385 if (!error)
386 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
387 iput(dir);
388 return error;
389 }
390
391 static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode)
392 {
393 struct nfs_sattr sattr;
394 struct nfs_fattr fattr;
395 struct nfs_fh fhandle;
396 int error;
397
398 if (!dir || !S_ISDIR(dir->i_mode)) {
399 printk("nfs_mkdir: inode is NULL or not a directory\n");
400 iput(dir);
401 return -ENOENT;
402 }
403 if (len > NFS_MAXNAMLEN) {
404 iput(dir);
405 return -ENAMETOOLONG;
406 }
407 sattr.mode = mode;
408 sattr.uid = sattr.gid = sattr.size = -1;
409 sattr.atime.seconds = sattr.mtime.seconds = -1;
410 error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir),
411 name, &sattr, &fhandle, &fattr);
412 if (!error)
413 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
414 iput(dir);
415 return error;
416 }
417
418 static int nfs_rmdir(struct inode *dir, const char *name, int len)
419 {
420 int error;
421
422 if (!dir || !S_ISDIR(dir->i_mode)) {
423 printk("nfs_rmdir: inode is NULL or not a directory\n");
424 iput(dir);
425 return -ENOENT;
426 }
427 if (len > NFS_MAXNAMLEN) {
428 iput(dir);
429 return -ENAMETOOLONG;
430 }
431 error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), name);
432 if (!error)
433 nfs_lookup_cache_remove(dir, NULL, name);
434 iput(dir);
435 return error;
436 }
437
438 static int nfs_unlink(struct inode *dir, const char *name, int len)
439 {
440 int error;
441
442 if (!dir || !S_ISDIR(dir->i_mode)) {
443 printk("nfs_unlink: inode is NULL or not a directory\n");
444 iput(dir);
445 return -ENOENT;
446 }
447 if (len > NFS_MAXNAMLEN) {
448 iput(dir);
449 return -ENAMETOOLONG;
450 }
451 error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), name);
452 if (!error)
453 nfs_lookup_cache_remove(dir, NULL, name);
454 iput(dir);
455 return error;
456 }
457
458 static int nfs_symlink(struct inode *dir, const char *name, int len,
459 const char *symname)
460 {
461 struct nfs_sattr sattr;
462 int error;
463
464 if (!dir || !S_ISDIR(dir->i_mode)) {
465 printk("nfs_symlink: inode is NULL or not a directory\n");
466 iput(dir);
467 return -ENOENT;
468 }
469 if (len > NFS_MAXNAMLEN) {
470 iput(dir);
471 return -ENAMETOOLONG;
472 }
473 if (strlen(symname) > NFS_MAXPATHLEN) {
474 iput(dir);
475 return -ENAMETOOLONG;
476 }
477 sattr.mode = S_IFLNK | 0777;
478 sattr.uid = sattr.gid = sattr.size = -1;
479 sattr.atime.seconds = sattr.mtime.seconds = -1;
480 error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir),
481 name, symname, &sattr);
482 iput(dir);
483 return error;
484 }
485
486 static int nfs_link(struct inode *oldinode, struct inode *dir,
487 const char *name, int len)
488 {
489 int error;
490
491 if (!oldinode) {
492 printk("nfs_link: old inode is NULL\n");
493 iput(oldinode);
494 iput(dir);
495 return -ENOENT;
496 }
497 if (!dir || !S_ISDIR(dir->i_mode)) {
498 printk("nfs_link: dir is NULL or not a directory\n");
499 iput(oldinode);
500 iput(dir);
501 return -ENOENT;
502 }
503 if (len > NFS_MAXNAMLEN) {
504 iput(oldinode);
505 iput(dir);
506 return -ENAMETOOLONG;
507 }
508 error = nfs_proc_link(NFS_SERVER(oldinode), NFS_FH(oldinode),
509 NFS_FH(dir), name);
510 if (!error)
511 nfs_lookup_cache_remove(dir, oldinode, NULL);
512 iput(oldinode);
513 iput(dir);
514 return error;
515 }
516
517 static int nfs_rename(struct inode *old_dir, const char *old_name, int old_len,
518 struct inode *new_dir, const char *new_name, int new_len)
519 {
520 int error;
521
522 if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
523 printk("nfs_rename: old inode is NULL or not a directory\n");
524 iput(old_dir);
525 iput(new_dir);
526 return -ENOENT;
527 }
528 if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
529 printk("nfs_rename: new inode is NULL or not a directory\n");
530 iput(old_dir);
531 iput(new_dir);
532 return -ENOENT;
533 }
534 if (old_len > NFS_MAXNAMLEN || new_len > NFS_MAXNAMLEN) {
535 iput(old_dir);
536 iput(new_dir);
537 return -ENAMETOOLONG;
538 }
539 error = nfs_proc_rename(NFS_SERVER(old_dir),
540 NFS_FH(old_dir), old_name,
541 NFS_FH(new_dir), new_name);
542 if (!error) {
543 nfs_lookup_cache_remove(old_dir, NULL, old_name);
544 nfs_lookup_cache_remove(new_dir, NULL, new_name);
545 }
546 iput(old_dir);
547 iput(new_dir);
548 return error;
549 }
550
551
552
553
554
555
556
557 void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
558 {
559 int was_empty;
560
561 if (!inode || !fattr) {
562 printk("nfs_refresh_inode: inode or fattr is NULL\n");
563 return;
564 }
565 if (inode->i_ino != fattr->fileid) {
566 printk("nfs_refresh_inode: inode number mismatch\n");
567 return;
568 }
569 was_empty = inode->i_mode == 0;
570 inode->i_mode = fattr->mode;
571 inode->i_nlink = fattr->nlink;
572 inode->i_uid = fattr->uid;
573 inode->i_gid = fattr->gid;
574 inode->i_size = fattr->size;
575 inode->i_blksize = fattr->blocksize;
576 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
577 inode->i_rdev = fattr->rdev;
578 else
579 inode->i_rdev = 0;
580 inode->i_blocks = fattr->blocks;
581 inode->i_atime = fattr->atime.seconds;
582 inode->i_mtime = fattr->mtime.seconds;
583 inode->i_ctime = fattr->ctime.seconds;
584 if (was_empty) {
585 if (S_ISREG(inode->i_mode))
586 inode->i_op = &nfs_file_inode_operations;
587 else if (S_ISDIR(inode->i_mode))
588 inode->i_op = &nfs_dir_inode_operations;
589 else if (S_ISLNK(inode->i_mode))
590 inode->i_op = &nfs_symlink_inode_operations;
591 else if (S_ISCHR(inode->i_mode))
592 inode->i_op = &chrdev_inode_operations;
593 else if (S_ISBLK(inode->i_mode))
594 inode->i_op = &blkdev_inode_operations;
595 else if (S_ISFIFO(inode->i_mode))
596 init_fifo(inode);
597 else
598 inode->i_op = NULL;
599 }
600 nfs_lookup_cache_refresh(inode, fattr);
601 }
602