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_unlink
- nfs_symlink
- nfs_link
- nfs_rename
- nfs_refresh_inode
1
2
3
4
5
6
7
8
9 #ifdef MODULE
10 #include <linux/module.h>
11 #endif
12
13 #include <linux/sched.h>
14 #include <linux/errno.h>
15 #include <linux/stat.h>
16 #include <linux/nfs_fs.h>
17 #include <linux/fcntl.h>
18 #include <linux/string.h>
19 #include <linux/kernel.h>
20 #include <linux/malloc.h>
21 #include <linux/mm.h>
22
23 #include <asm/segment.h>
24
25 static int nfs_dir_read(struct inode *, struct file *filp, char *buf,
26 int count);
27 static int nfs_readdir(struct inode *, struct file *, void *, filldir_t);
28 static int nfs_lookup(struct inode *dir, const char *name, int len,
29 struct inode **result);
30 static int nfs_create(struct inode *dir, const char *name, int len, int mode,
31 struct inode **result);
32 static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode);
33 static int nfs_rmdir(struct inode *dir, const char *name, int len);
34 static int nfs_unlink(struct inode *dir, const char *name, int len);
35 static int nfs_symlink(struct inode *inode, const char *name, int len,
36 const char *symname);
37 static int nfs_link(struct inode *oldinode, struct inode *dir,
38 const char *name, int len);
39 static int nfs_mknod(struct inode *dir, const char *name, int len, int mode,
40 int rdev);
41 static int nfs_rename(struct inode *old_dir, const char *old_name,
42 int old_len, struct inode *new_dir, const char *new_name,
43 int new_len);
44
45 static struct file_operations nfs_dir_operations = {
46 NULL,
47 nfs_dir_read,
48 NULL,
49 nfs_readdir,
50 NULL,
51 NULL,
52 NULL,
53 NULL,
54 NULL,
55 NULL
56 };
57
58 struct inode_operations nfs_dir_inode_operations = {
59 &nfs_dir_operations,
60 nfs_create,
61 nfs_lookup,
62 nfs_link,
63 nfs_unlink,
64 nfs_symlink,
65 nfs_mkdir,
66 nfs_rmdir,
67 nfs_mknod,
68 nfs_rename,
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_unlink(struct inode *dir, const char *name, int len)
487 {
488 int error;
489
490 if (!dir || !S_ISDIR(dir->i_mode)) {
491 printk("nfs_unlink: inode is NULL or not a directory\n");
492 iput(dir);
493 return -ENOENT;
494 }
495 if (len > NFS_MAXNAMLEN) {
496 iput(dir);
497 return -ENAMETOOLONG;
498 }
499 error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), name);
500 if (!error)
501 nfs_lookup_cache_remove(dir, NULL, name);
502 iput(dir);
503 return error;
504 }
505
506 static int nfs_symlink(struct inode *dir, const char *name, int len,
507 const char *symname)
508 {
509 struct nfs_sattr sattr;
510 int error;
511
512 if (!dir || !S_ISDIR(dir->i_mode)) {
513 printk("nfs_symlink: inode is NULL or not a directory\n");
514 iput(dir);
515 return -ENOENT;
516 }
517 if (len > NFS_MAXNAMLEN) {
518 iput(dir);
519 return -ENAMETOOLONG;
520 }
521 if (strlen(symname) > NFS_MAXPATHLEN) {
522 iput(dir);
523 return -ENAMETOOLONG;
524 }
525 sattr.mode = S_IFLNK | S_IRWXUGO;
526 sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
527 sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
528 error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir),
529 name, symname, &sattr);
530 iput(dir);
531 return error;
532 }
533
534 static int nfs_link(struct inode *oldinode, struct inode *dir,
535 const char *name, int len)
536 {
537 int error;
538
539 if (!oldinode) {
540 printk("nfs_link: old inode is NULL\n");
541 iput(oldinode);
542 iput(dir);
543 return -ENOENT;
544 }
545 if (!dir || !S_ISDIR(dir->i_mode)) {
546 printk("nfs_link: dir is NULL or not a directory\n");
547 iput(oldinode);
548 iput(dir);
549 return -ENOENT;
550 }
551 if (len > NFS_MAXNAMLEN) {
552 iput(oldinode);
553 iput(dir);
554 return -ENAMETOOLONG;
555 }
556 error = nfs_proc_link(NFS_SERVER(oldinode), NFS_FH(oldinode),
557 NFS_FH(dir), name);
558 if (!error)
559 nfs_lookup_cache_remove(dir, oldinode, NULL);
560 iput(oldinode);
561 iput(dir);
562 return error;
563 }
564
565 static int nfs_rename(struct inode *old_dir, const char *old_name, int old_len,
566 struct inode *new_dir, const char *new_name, int new_len)
567 {
568 int error;
569
570 if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
571 printk("nfs_rename: old inode is NULL or not a directory\n");
572 iput(old_dir);
573 iput(new_dir);
574 return -ENOENT;
575 }
576 if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
577 printk("nfs_rename: new inode is NULL or not a directory\n");
578 iput(old_dir);
579 iput(new_dir);
580 return -ENOENT;
581 }
582 if (old_len > NFS_MAXNAMLEN || new_len > NFS_MAXNAMLEN) {
583 iput(old_dir);
584 iput(new_dir);
585 return -ENAMETOOLONG;
586 }
587 error = nfs_proc_rename(NFS_SERVER(old_dir),
588 NFS_FH(old_dir), old_name,
589 NFS_FH(new_dir), new_name);
590 if (!error) {
591 nfs_lookup_cache_remove(old_dir, NULL, old_name);
592 nfs_lookup_cache_remove(new_dir, NULL, new_name);
593 }
594 iput(old_dir);
595 iput(new_dir);
596 return error;
597 }
598
599
600
601
602
603
604
605 void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
606 {
607 int was_empty;
608
609 if (!inode || !fattr) {
610 printk("nfs_refresh_inode: inode or fattr is NULL\n");
611 return;
612 }
613 if (inode->i_ino != fattr->fileid) {
614 printk("nfs_refresh_inode: inode number mismatch\n");
615 return;
616 }
617 was_empty = inode->i_mode == 0;
618 inode->i_mode = fattr->mode;
619 inode->i_nlink = fattr->nlink;
620 inode->i_uid = fattr->uid;
621 inode->i_gid = fattr->gid;
622 inode->i_size = fattr->size;
623 inode->i_blksize = fattr->blocksize;
624 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
625 inode->i_rdev = to_kdev_t(fattr->rdev);
626 else
627 inode->i_rdev = 0;
628 inode->i_blocks = fattr->blocks;
629 inode->i_atime = fattr->atime.seconds;
630 inode->i_mtime = fattr->mtime.seconds;
631 inode->i_ctime = fattr->ctime.seconds;
632 if (was_empty) {
633 if (S_ISREG(inode->i_mode))
634 inode->i_op = &nfs_file_inode_operations;
635 else if (S_ISDIR(inode->i_mode))
636 inode->i_op = &nfs_dir_inode_operations;
637 else if (S_ISLNK(inode->i_mode))
638 inode->i_op = &nfs_symlink_inode_operations;
639 else if (S_ISCHR(inode->i_mode))
640 inode->i_op = &chrdev_inode_operations;
641 else if (S_ISBLK(inode->i_mode))
642 inode->i_op = &blkdev_inode_operations;
643 else if (S_ISFIFO(inode->i_mode))
644 init_fifo(inode);
645 else
646 inode->i_op = NULL;
647 }
648 nfs_lookup_cache_refresh(inode, fattr);
649 }
650