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