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