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