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