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