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