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