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