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