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 int 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 int 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 && entry->inode == dir->i_ino
235 && !strncmp(filename, entry->filename, NFS_MAXNAMLEN))
236 return entry;
237 }
238 return NULL;
239 }
240
241 static int nfs_lookup_cache_lookup(struct inode *dir, const char *filename,
242 struct nfs_fh *fhandle,
243 struct nfs_fattr *fattr)
244 {
245 static int nfs_lookup_cache_in_use = 0;
246
247 struct nfs_lookup_cache_entry *entry;
248
249 if (!nfs_lookup_cache_in_use) {
250 memset(nfs_lookup_cache, 0, sizeof(nfs_lookup_cache));
251 nfs_lookup_cache_in_use = 1;
252 }
253 if ((entry = nfs_lookup_cache_index(dir, filename))) {
254 if (jiffies > entry->expiration_date) {
255 entry->dev = 0;
256 return 0;
257 }
258 *fhandle = entry->fhandle;
259 *fattr = entry->fattr;
260 return 1;
261 }
262 return 0;
263 }
264
265 static void nfs_lookup_cache_add(struct inode *dir, const char *filename,
266 struct nfs_fh *fhandle,
267 struct nfs_fattr *fattr)
268 {
269 static int nfs_lookup_cache_pos = 0;
270 struct nfs_lookup_cache_entry *entry;
271
272
273 if (fattr->size == -1 || fattr->uid == -1 || fattr->gid == -1
274 || fattr->atime.seconds == -1 || fattr->mtime.seconds == -1)
275 return;
276 if (!(entry = nfs_lookup_cache_index(dir, filename))) {
277 entry = nfs_lookup_cache + nfs_lookup_cache_pos++;
278 if (nfs_lookup_cache_pos == NFS_LOOKUP_CACHE_SIZE)
279 nfs_lookup_cache_pos = 0;
280 }
281 entry->dev = dir->i_dev;
282 entry->inode = dir->i_ino;
283 strcpy(entry->filename, filename);
284 entry->fhandle = *fhandle;
285 entry->fattr = *fattr;
286 entry->expiration_date = jiffies + (S_ISDIR(fattr->mode)
287 ? NFS_SERVER(dir)->acdirmin : NFS_SERVER(dir)->acregmin);
288 }
289
290 static void nfs_lookup_cache_remove(struct inode *dir, struct inode *inode,
291 const char *filename)
292 {
293 struct nfs_lookup_cache_entry *entry;
294 int dev;
295 int fileid;
296 int i;
297
298 if (inode) {
299 dev = inode->i_dev;
300 fileid = inode->i_ino;
301 }
302 else if ((entry = nfs_lookup_cache_index(dir, filename))) {
303 dev = entry->dev;
304 fileid = entry->fattr.fileid;
305 }
306 else
307 return;
308 for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
309 entry = nfs_lookup_cache + i;
310 if (entry->dev == dev && entry->fattr.fileid == fileid)
311 entry->dev = 0;
312 }
313 }
314
315 static void nfs_lookup_cache_refresh(struct inode *file,
316 struct nfs_fattr *fattr)
317 {
318 struct nfs_lookup_cache_entry *entry;
319 int dev = file->i_dev;
320 int fileid = file->i_ino;
321 int i;
322
323 for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
324 entry = nfs_lookup_cache + i;
325 if (entry->dev == dev && entry->fattr.fileid == fileid)
326 entry->fattr = *fattr;
327 }
328 }
329
330 static int nfs_lookup(struct inode *dir, const char *__name, int len,
331 struct inode **result)
332 {
333 struct nfs_fh fhandle;
334 struct nfs_fattr fattr;
335 char name[len > NFS_MAXNAMLEN? 1 : len+1];
336 int error;
337
338 *result = NULL;
339 if (!dir || !S_ISDIR(dir->i_mode)) {
340 printk("nfs_lookup: inode is NULL or not a directory\n");
341 iput(dir);
342 return -ENOENT;
343 }
344 if (len > NFS_MAXNAMLEN) {
345 iput(dir);
346 return -ENAMETOOLONG;
347 }
348 memcpy(name,__name,len);
349 name[len] = '\0';
350 if (len == 1 && name[0] == '.') {
351 *result = dir;
352 return 0;
353 }
354 if ((NFS_SERVER(dir)->flags & NFS_MOUNT_NOAC)
355 || !nfs_lookup_cache_lookup(dir, name, &fhandle, &fattr)) {
356 if ((error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir),
357 name, &fhandle, &fattr))) {
358 iput(dir);
359 return error;
360 }
361 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
362 }
363 if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) {
364 iput(dir);
365 return -EACCES;
366 }
367 iput(dir);
368 return 0;
369 }
370
371 static int nfs_create(struct inode *dir, const char *name, int len, int mode,
372 struct inode **result)
373 {
374 struct nfs_sattr sattr;
375 struct nfs_fattr fattr;
376 struct nfs_fh fhandle;
377 int error;
378
379 *result = NULL;
380 if (!dir || !S_ISDIR(dir->i_mode)) {
381 printk("nfs_create: inode is NULL or not a directory\n");
382 iput(dir);
383 return -ENOENT;
384 }
385 if (len > NFS_MAXNAMLEN) {
386 iput(dir);
387 return -ENAMETOOLONG;
388 }
389 sattr.mode = mode;
390 sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
391 sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
392 if ((error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
393 name, &sattr, &fhandle, &fattr))) {
394 iput(dir);
395 return error;
396 }
397 if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) {
398 iput(dir);
399 return -EACCES;
400 }
401 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
402 iput(dir);
403 return 0;
404 }
405
406 static int nfs_mknod(struct inode *dir, const char *name, int len,
407 int mode, int rdev)
408 {
409 struct nfs_sattr sattr;
410 struct nfs_fattr fattr;
411 struct nfs_fh fhandle;
412 int error;
413
414 if (!dir || !S_ISDIR(dir->i_mode)) {
415 printk("nfs_mknod: inode is NULL or not a directory\n");
416 iput(dir);
417 return -ENOENT;
418 }
419 if (len > NFS_MAXNAMLEN) {
420 iput(dir);
421 return -ENAMETOOLONG;
422 }
423 sattr.mode = mode;
424 sattr.uid = sattr.gid = (unsigned) -1;
425 if (S_ISCHR(mode) || S_ISBLK(mode))
426 sattr.size = rdev;
427 else
428 sattr.size = (unsigned) -1;
429 sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
430 error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
431 name, &sattr, &fhandle, &fattr);
432 if (!error)
433 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
434 iput(dir);
435 return error;
436 }
437
438 static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode)
439 {
440 struct nfs_sattr sattr;
441 struct nfs_fattr fattr;
442 struct nfs_fh fhandle;
443 int error;
444
445 if (!dir || !S_ISDIR(dir->i_mode)) {
446 printk("nfs_mkdir: inode is NULL or not a directory\n");
447 iput(dir);
448 return -ENOENT;
449 }
450 if (len > NFS_MAXNAMLEN) {
451 iput(dir);
452 return -ENAMETOOLONG;
453 }
454 sattr.mode = mode;
455 sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
456 sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
457 error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir),
458 name, &sattr, &fhandle, &fattr);
459 if (!error)
460 nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
461 iput(dir);
462 return error;
463 }
464
465 static int nfs_rmdir(struct inode *dir, const char *name, int len)
466 {
467 int error;
468
469 if (!dir || !S_ISDIR(dir->i_mode)) {
470 printk("nfs_rmdir: inode is NULL or not a directory\n");
471 iput(dir);
472 return -ENOENT;
473 }
474 if (len > NFS_MAXNAMLEN) {
475 iput(dir);
476 return -ENAMETOOLONG;
477 }
478 error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), name);
479 if (!error)
480 nfs_lookup_cache_remove(dir, NULL, name);
481 iput(dir);
482 return error;
483 }
484
485 static int nfs_unlink(struct inode *dir, const char *name, int len)
486 {
487 int error;
488
489 if (!dir || !S_ISDIR(dir->i_mode)) {
490 printk("nfs_unlink: 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_remove(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_symlink(struct inode *dir, const char *name, int len,
506 const char *symname)
507 {
508 struct nfs_sattr sattr;
509 int error;
510
511 if (!dir || !S_ISDIR(dir->i_mode)) {
512 printk("nfs_symlink: inode is NULL or not a directory\n");
513 iput(dir);
514 return -ENOENT;
515 }
516 if (len > NFS_MAXNAMLEN) {
517 iput(dir);
518 return -ENAMETOOLONG;
519 }
520 if (strlen(symname) > NFS_MAXPATHLEN) {
521 iput(dir);
522 return -ENAMETOOLONG;
523 }
524 sattr.mode = S_IFLNK | S_IRWXUGO;
525 sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
526 sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
527 error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir),
528 name, symname, &sattr);
529 iput(dir);
530 return error;
531 }
532
533 static int nfs_link(struct inode *oldinode, struct inode *dir,
534 const char *name, int len)
535 {
536 int error;
537
538 if (!oldinode) {
539 printk("nfs_link: old inode is NULL\n");
540 iput(oldinode);
541 iput(dir);
542 return -ENOENT;
543 }
544 if (!dir || !S_ISDIR(dir->i_mode)) {
545 printk("nfs_link: dir is NULL or not a directory\n");
546 iput(oldinode);
547 iput(dir);
548 return -ENOENT;
549 }
550 if (len > NFS_MAXNAMLEN) {
551 iput(oldinode);
552 iput(dir);
553 return -ENAMETOOLONG;
554 }
555 error = nfs_proc_link(NFS_SERVER(oldinode), NFS_FH(oldinode),
556 NFS_FH(dir), name);
557 if (!error)
558 nfs_lookup_cache_remove(dir, oldinode, NULL);
559 iput(oldinode);
560 iput(dir);
561 return error;
562 }
563
564 static int nfs_rename(struct inode *old_dir, const char *old_name, int old_len,
565 struct inode *new_dir, const char *new_name, int new_len)
566 {
567 int error;
568
569 if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
570 printk("nfs_rename: old inode is NULL or not a directory\n");
571 iput(old_dir);
572 iput(new_dir);
573 return -ENOENT;
574 }
575 if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
576 printk("nfs_rename: new inode is NULL or not a directory\n");
577 iput(old_dir);
578 iput(new_dir);
579 return -ENOENT;
580 }
581 if (old_len > NFS_MAXNAMLEN || new_len > NFS_MAXNAMLEN) {
582 iput(old_dir);
583 iput(new_dir);
584 return -ENAMETOOLONG;
585 }
586 error = nfs_proc_rename(NFS_SERVER(old_dir),
587 NFS_FH(old_dir), old_name,
588 NFS_FH(new_dir), new_name);
589 if (!error) {
590 nfs_lookup_cache_remove(old_dir, NULL, old_name);
591 nfs_lookup_cache_remove(new_dir, NULL, new_name);
592 }
593 iput(old_dir);
594 iput(new_dir);
595 return error;
596 }
597
598
599
600
601
602
603
604 void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
605 {
606 int was_empty;
607
608 if (!inode || !fattr) {
609 printk("nfs_refresh_inode: inode or fattr is NULL\n");
610 return;
611 }
612 if (inode->i_ino != fattr->fileid) {
613 printk("nfs_refresh_inode: inode number mismatch\n");
614 return;
615 }
616 was_empty = inode->i_mode == 0;
617 inode->i_mode = fattr->mode;
618 inode->i_nlink = fattr->nlink;
619 inode->i_uid = fattr->uid;
620 inode->i_gid = fattr->gid;
621 inode->i_size = fattr->size;
622 inode->i_blksize = fattr->blocksize;
623 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
624 inode->i_rdev = fattr->rdev;
625 else
626 inode->i_rdev = 0;
627 inode->i_blocks = fattr->blocks;
628 inode->i_atime = fattr->atime.seconds;
629 inode->i_mtime = fattr->mtime.seconds;
630 inode->i_ctime = fattr->ctime.seconds;
631 if (was_empty) {
632 if (S_ISREG(inode->i_mode))
633 inode->i_op = &nfs_file_inode_operations;
634 else if (S_ISDIR(inode->i_mode))
635 inode->i_op = &nfs_dir_inode_operations;
636 else if (S_ISLNK(inode->i_mode))
637 inode->i_op = &nfs_symlink_inode_operations;
638 else if (S_ISCHR(inode->i_mode))
639 inode->i_op = &chrdev_inode_operations;
640 else if (S_ISBLK(inode->i_mode))
641 inode->i_op = &blkdev_inode_operations;
642 else if (S_ISFIFO(inode->i_mode))
643 init_fifo(inode);
644 else
645 inode->i_op = NULL;
646 }
647 nfs_lookup_cache_refresh(inode, fattr);
648 }
649