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