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