OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [nfs/] [dir.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/nfs/dir.c
3
 *
4
 *  Copyright (C) 1992  Rick Sladkey
5
 *
6
 *  nfs directory handling functions
7
 *
8
 * 10 Apr 1996  Added silly rename for unlink   --okir
9
 */
10
 
11
/*
12
 * Fixes:
13
 *    Ion Badulescu <ionut@cs.columbia.edu>     : FIFO's need special handling in NFSv2
14
 */
15
 
16
#include <linux/sched.h>
17
#include <linux/errno.h>
18
#include <linux/stat.h>
19
#include <linux/nfs_fs.h>
20
#include <linux/fcntl.h>
21
#include <linux/string.h>
22
#include <linux/kernel.h>
23
#include <linux/malloc.h>
24
#include <linux/mm.h>
25
 
26
#include <asm/segment.h>        /* for fs functions */
27
 
28
static int nfs_dir_open(struct inode * inode, struct file * file);
29
static int nfs_dir_read(struct inode *, struct file *, char *, int);
30
static int nfs_readdir(struct inode *, struct file *, void *, filldir_t);
31
static int nfs_lookup(struct inode *, const char *, int, struct inode **);
32
static int nfs_create(struct inode *, const char *, int, int, struct inode **);
33
static int nfs_mkdir(struct inode *, const char *, int, int);
34
static int nfs_rmdir(struct inode *, const char *, int);
35
static int nfs_unlink(struct inode *, const char *, int);
36
static int nfs_symlink(struct inode *, const char *, int, const char *);
37
static int nfs_link(struct inode *, struct inode *, const char *, int);
38
static int nfs_mknod(struct inode *, const char *, int, int, int);
39
static int nfs_rename(struct inode *, const char *, int,
40
                      struct inode *, const char *, int, int);
41
 
42
static struct file_operations nfs_dir_operations = {
43
        NULL,                   /* lseek - default */
44
        nfs_dir_read,           /* read - bad */
45
        NULL,                   /* write - bad */
46
        nfs_readdir,            /* readdir */
47
        NULL,                   /* select - default */
48
        NULL,                   /* ioctl - default */
49
        NULL,                   /* mmap */
50
        nfs_dir_open,           /* open - revalidate */
51
        NULL,                   /* no special release code */
52
        NULL                    /* fsync */
53
};
54
 
55
struct inode_operations nfs_dir_inode_operations = {
56
        &nfs_dir_operations,    /* default directory file-ops */
57
        nfs_create,             /* create */
58
        nfs_lookup,             /* lookup */
59
        nfs_link,               /* link */
60
        nfs_unlink,             /* unlink */
61
        nfs_symlink,            /* symlink */
62
        nfs_mkdir,              /* mkdir */
63
        nfs_rmdir,              /* rmdir */
64
        nfs_mknod,              /* mknod */
65
        nfs_rename,             /* rename */
66
        NULL,                   /* readlink */
67
        NULL,                   /* follow_link */
68
        NULL,                   /* readpage */
69
        NULL,                   /* writepage */
70
        NULL,                   /* bmap */
71
        NULL,                   /* truncate */
72
        NULL                    /* permission */
73
};
74
 
75
static inline void revalidate_dir(struct nfs_server * server, struct inode * dir)
76
{
77
        struct nfs_fattr fattr;
78
 
79
        if (jiffies - NFS_READTIME(dir) < NFS_ATTRTIMEO(dir))
80
                return;
81
 
82
        NFS_READTIME(dir) = jiffies;
83
        if (nfs_proc_getattr(server, NFS_FH(dir), &fattr) == 0) {
84
                nfs_refresh_inode(dir, &fattr);
85
                if (fattr.mtime.seconds == NFS_OLDMTIME(dir)) {
86
                        if ((NFS_ATTRTIMEO(dir) <<= 1) > server->acdirmax)
87
                                NFS_ATTRTIMEO(dir) = server->acdirmax;
88
                        return;
89
                }
90
                NFS_OLDMTIME(dir) = fattr.mtime.seconds;
91
        }
92
        /* invalidate directory cache here when we _really_ start caching */
93
}
94
 
95
static int nfs_dir_open(struct inode * dir, struct file * file)
96
{
97
        revalidate_dir(NFS_SERVER(dir), dir);
98
        return 0;
99
}
100
 
101
static int nfs_dir_read(struct inode *inode, struct file *filp, char *buf,
102
                        int count)
103
{
104
        return -EISDIR;
105
}
106
 
107
static struct nfs_entry *c_entry = NULL;
108
 
109
/*
110
 * We need to do caching of directory entries to prevent an
111
 * incredible amount of RPC traffic.  Only the most recent open
112
 * directory is cached.  This seems sufficient for most purposes.
113
 * Technically, we ought to flush the cache on close but this is
114
 * not a problem in practice.
115
 */
116
 
117
static int nfs_readdir(struct inode *inode, struct file *filp,
118
                       void *dirent, filldir_t filldir)
119
{
120
        static kdev_t c_dev = 0;
121
        static int c_ino;
122
        static int c_size;
123
 
124
        int result;
125
        int i, index = 0;
126
        struct nfs_entry *entry;
127
 
128
        if (!inode || !S_ISDIR(inode->i_mode)) {
129
                printk("nfs_readdir: inode is NULL or not a directory\n");
130
                return -EBADF;
131
        }
132
 
133
        revalidate_dir(NFS_SERVER(inode), inode);
134
 
135
        /* initialize cache memory if it hasn't been used before */
136
 
137
        if (c_entry == NULL) {
138
                i = sizeof (struct nfs_entry)*NFS_READDIR_CACHE_SIZE;
139
                c_entry = (struct nfs_entry *) kmalloc(i, GFP_KERNEL);
140
                if (c_entry == NULL) {
141
                        printk("nfs_readdir: no MEMORY for cache\n");
142
                        return -ENOMEM;
143
                }
144
                for (i = 0; i < NFS_READDIR_CACHE_SIZE; i++) {
145
                        c_entry[i].name = (char *) kmalloc(NFS_MAXNAMLEN + 1,
146
                                GFP_KERNEL);
147
                        if (c_entry[i].name == NULL) {
148
                                printk("nfs_readdir: no MEMORY for cache\n");
149
                                while (--i>=0)
150
                                        kfree(c_entry[i].name);
151
                                kfree(c_entry);
152
                                c_entry = NULL;
153
                                return -ENOMEM;
154
                        }
155
                }
156
        }
157
        entry = NULL;
158
 
159
        /* try to find it in the cache */
160
 
161
        if (inode->i_dev == c_dev && inode->i_ino == c_ino) {
162
                for (i = 0; i < c_size; i++) {
163
                        if (filp->f_pos == c_entry[i].cookie) {
164
                                if (i == c_size - 1) {
165
                                        if (c_entry[i].eof)
166
                                                return 0;
167
                                }
168
                                else
169
                                        entry = c_entry + (index = i + 1);
170
                                break;
171
                        }
172
                }
173
        }
174
 
175
        /* if we didn't find it in the cache, revert to an nfs call */
176
 
177
        if (!entry) {
178
                result = nfs_proc_readdir(NFS_SERVER(inode), NFS_FH(inode),
179
                        filp->f_pos, NFS_READDIR_CACHE_SIZE, c_entry);
180
                if (result < 0) {
181
                        c_dev = 0;
182
                        return result;
183
                }
184
                if (result > 0) {
185
                        c_dev = inode->i_dev;
186
                        c_ino = inode->i_ino;
187
                        c_size = result;
188
                        entry = c_entry + (index = 0);
189
                }
190
        }
191
 
192
        /* if we found it in the cache or from an nfs call, return results */
193
        if (!entry)
194
                return 0;
195
        while (index < c_size) {
196
                int nextpos = entry->cookie;
197
                if (filldir(dirent, entry->name, strlen(entry->name), filp->f_pos, entry->fileid) < 0)
198
                        break;
199
                filp->f_pos = nextpos;
200
                /* revalidate the cache if we slept in filldir() */
201
                if (inode->i_dev != c_dev)
202
                        break;
203
                if (inode->i_ino != c_ino)
204
                        break;
205
                if (nextpos != entry->cookie)
206
                        break;
207
                index++;
208
                entry++;
209
        }
210
        return 0;
211
}
212
 
213
/*
214
 * free cache memory
215
 * called from cleanup_module
216
 */
217
 
218
void nfs_kfree_cache(void)
219
{
220
        int i;
221
 
222
        if (c_entry == NULL)
223
                return;
224
        for (i = 0; i < NFS_READDIR_CACHE_SIZE; i++)
225
                kfree(c_entry[i].name);
226
        kfree(c_entry);
227
        c_entry = NULL;
228
}
229
 
230
 
231
/*
232
 * Lookup caching is a big win for performance but this is just
233
 * a trial to see how well it works on a small scale.
234
 * For example, bash does a lookup on ".." 13 times for each path
235
 * element when running pwd.  Yes, hard to believe but true.
236
 * Try pwd in a filesystem mounted with noac.
237
 *
238
 * It trades a little cpu time and memory for a lot of network bandwidth.
239
 * Since the cache is not hashed yet, it is a good idea not to make it too
240
 * large because every lookup looks through the entire cache even
241
 * though most of them will fail.
242
 */
243
 
244
static struct nfs_lookup_cache_entry {
245
        kdev_t dev;
246
        int inode;
247
        char filename[NFS_MAXNAMLEN + 1];
248
        struct nfs_fh fhandle;
249
        struct nfs_fattr fattr;
250
        int expiration_date;
251
} nfs_lookup_cache[NFS_LOOKUP_CACHE_SIZE];
252
 
253
static struct nfs_lookup_cache_entry *nfs_lookup_cache_index(struct inode *dir,
254
                                                             const char *filename)
255
{
256
        struct nfs_lookup_cache_entry *entry;
257
        int i;
258
 
259
        for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
260
                entry = nfs_lookup_cache + i;
261
                if (entry->dev == dir->i_dev
262
                    && entry->inode == dir->i_ino
263
                    && !strncmp(filename, entry->filename, NFS_MAXNAMLEN))
264
                        return entry;
265
        }
266
        return NULL;
267
}
268
 
269
static int nfs_lookup_cache_lookup(struct inode *dir, const char *filename,
270
                                   struct nfs_fh *fhandle,
271
                                   struct nfs_fattr *fattr)
272
{
273
        static int nfs_lookup_cache_in_use = 0;
274
 
275
        struct nfs_lookup_cache_entry *entry;
276
 
277
        if (!nfs_lookup_cache_in_use) {
278
                memset(nfs_lookup_cache, 0, sizeof(nfs_lookup_cache));
279
                nfs_lookup_cache_in_use = 1;
280
        }
281
        if ((entry = nfs_lookup_cache_index(dir, filename))) {
282
                if (jiffies > entry->expiration_date) {
283
                        entry->dev = 0;
284
                        return 0;
285
                }
286
                *fhandle = entry->fhandle;
287
                *fattr = entry->fattr;
288
                return 1;
289
        }
290
        return 0;
291
}
292
 
293
static void nfs_lookup_cache_add(struct inode *dir, const char *filename,
294
                                 struct nfs_fh *fhandle,
295
                                 struct nfs_fattr *fattr)
296
{
297
        static int nfs_lookup_cache_pos = 0;
298
        struct nfs_lookup_cache_entry *entry;
299
 
300
        /* compensate for bug in SGI NFS server */
301
        if (fattr->size == -1 || fattr->uid == -1 || fattr->gid == -1
302
            || fattr->atime.seconds == -1 || fattr->mtime.seconds == -1)
303
                return;
304
        if (!(entry = nfs_lookup_cache_index(dir, filename))) {
305
                entry = nfs_lookup_cache + nfs_lookup_cache_pos++;
306
                if (nfs_lookup_cache_pos == NFS_LOOKUP_CACHE_SIZE)
307
                        nfs_lookup_cache_pos = 0;
308
        }
309
        entry->dev = dir->i_dev;
310
        entry->inode = dir->i_ino;
311
        strcpy(entry->filename, filename);
312
        entry->fhandle = *fhandle;
313
        entry->fattr = *fattr;
314
        entry->expiration_date = jiffies + (S_ISDIR(fattr->mode)
315
                ? NFS_SERVER(dir)->acdirmin : NFS_SERVER(dir)->acregmin);
316
}
317
 
318
static void nfs_lookup_cache_remove(struct inode *dir, struct inode *inode,
319
                                    const char *filename)
320
{
321
        struct nfs_lookup_cache_entry *entry;
322
        kdev_t dev;
323
        int fileid;
324
        int i;
325
 
326
        if (inode) {
327
                dev = inode->i_dev;
328
                fileid = inode->i_ino;
329
        }
330
        else if ((entry = nfs_lookup_cache_index(dir, filename))) {
331
                dev = entry->dev;
332
                fileid = entry->fattr.fileid;
333
        }
334
        else
335
                return;
336
        for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
337
                entry = nfs_lookup_cache + i;
338
                if (entry->dev == dev && entry->fattr.fileid == fileid)
339
                        entry->dev = 0;
340
        }
341
}
342
 
343
static void nfs_lookup_cache_refresh(struct inode *file,
344
                                     struct nfs_fattr *fattr)
345
{
346
        struct nfs_lookup_cache_entry *entry;
347
        kdev_t dev = file->i_dev;
348
        int fileid = file->i_ino;
349
        int i;
350
 
351
        for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
352
                entry = nfs_lookup_cache + i;
353
                if (entry->dev == dev && entry->fattr.fileid == fileid)
354
                        entry->fattr = *fattr;
355
        }
356
}
357
 
358
static int nfs_lookup(struct inode *dir, const char *__name, int len,
359
                      struct inode **result)
360
{
361
        struct nfs_fh fhandle;
362
        struct nfs_fattr fattr;
363
        char name[len > NFS_MAXNAMLEN? 1 : len+1];
364
        int error;
365
 
366
        *result = NULL;
367
        if (!dir || !S_ISDIR(dir->i_mode)) {
368
                printk("nfs_lookup: inode is NULL or not a directory\n");
369
                iput(dir);
370
                return -ENOENT;
371
        }
372
        if (len > NFS_MAXNAMLEN) {
373
                iput(dir);
374
                return -ENAMETOOLONG;
375
        }
376
        memcpy(name,__name,len);
377
        name[len] = '\0';
378
        if (len == 1 && name[0] == '.') { /* cheat for "." */
379
                *result = dir;
380
                return 0;
381
        }
382
        if ((NFS_SERVER(dir)->flags & NFS_MOUNT_NOAC)
383
            || !nfs_lookup_cache_lookup(dir, name, &fhandle, &fattr)) {
384
                if ((error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir),
385
                    name, &fhandle, &fattr))) {
386
                        iput(dir);
387
                        return error;
388
                }
389
                nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
390
        }
391
        if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) {
392
                iput(dir);
393
                return -EACCES;
394
        }
395
        iput(dir);
396
        return 0;
397
}
398
 
399
static int nfs_create(struct inode *dir, const char *name, int len, int mode,
400
                      struct inode **result)
401
{
402
        struct nfs_sattr sattr;
403
        struct nfs_fattr fattr;
404
        struct nfs_fh fhandle;
405
        int error;
406
 
407
        *result = NULL;
408
        if (!dir || !S_ISDIR(dir->i_mode)) {
409
                printk("nfs_create: inode is NULL or not a directory\n");
410
                iput(dir);
411
                return -ENOENT;
412
        }
413
        if (len > NFS_MAXNAMLEN) {
414
                iput(dir);
415
                return -ENAMETOOLONG;
416
        }
417
        sattr.mode = mode;
418
        sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
419
        sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
420
        if ((error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
421
                name, &sattr, &fhandle, &fattr))) {
422
                iput(dir);
423
                return error;
424
        }
425
        if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) {
426
                iput(dir);
427
                return -EACCES;
428
        }
429
        nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
430
        iput(dir);
431
        return 0;
432
}
433
 
434
static int nfs_mknod(struct inode *dir, const char *name, int len,
435
                     int mode, int rdev)
436
{
437
        struct nfs_sattr sattr;
438
        struct nfs_fattr fattr;
439
        struct nfs_fh fhandle;
440
        int error;
441
 
442
        if (!dir || !S_ISDIR(dir->i_mode)) {
443
                printk("nfs_mknod: inode is NULL or not a directory\n");
444
                iput(dir);
445
                return -ENOENT;
446
        }
447
        if (len > NFS_MAXNAMLEN) {
448
                iput(dir);
449
                return -ENAMETOOLONG;
450
        }
451
        if (S_ISFIFO(mode))
452
                sattr.mode = (mode & ~S_IFMT) | S_IFCHR;
453
        else
454
                sattr.mode = mode;
455
        sattr.uid = sattr.gid = (unsigned) -1;
456
        if (S_ISCHR(mode) || S_ISBLK(mode))
457
                sattr.size = rdev; /* get out your barf bag */
458
        else
459
                sattr.size = (unsigned) -1;
460
        sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
461
        error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
462
                name, &sattr, &fhandle, &fattr);
463
        if (error == -EINVAL && (S_ISFIFO(mode))) {
464
                sattr.mode = mode;
465
                error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
466
                                        name, &sattr, &fhandle, &fattr);
467
        }
468
        if (!error)
469
        {
470
                nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
471
                /* The parent dir inode count may have changed ! */
472
                nfs_lookup_cache_remove( NULL, dir, NULL);
473
        }
474
 
475
        iput(dir);
476
        return error;
477
}
478
 
479
static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode)
480
{
481
        struct nfs_sattr sattr;
482
        struct nfs_fattr fattr;
483
        struct nfs_fh fhandle;
484
        int error;
485
 
486
        if (!dir || !S_ISDIR(dir->i_mode)) {
487
                printk("nfs_mkdir: inode is NULL or not a directory\n");
488
                iput(dir);
489
                return -ENOENT;
490
        }
491
        if (len > NFS_MAXNAMLEN) {
492
                iput(dir);
493
                return -ENAMETOOLONG;
494
        }
495
        sattr.mode = mode;
496
        sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
497
        sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
498
        error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir),
499
                name, &sattr, &fhandle, &fattr);
500
        if (!error) {
501
                if (fattr.fileid == dir->i_ino)
502
                        printk("Sony NewsOS 4.1R buggy nfs server?\n");
503
                else
504
                        nfs_lookup_cache_add(dir, name, &fhandle, &fattr);
505
        }
506
        iput(dir);
507
        /* The parent dir link count may have changed */
508
        nfs_lookup_cache_remove( NULL, dir, NULL);
509
        return error;
510
}
511
 
512
static int nfs_rmdir(struct inode *dir, const char *name, int len)
513
{
514
        int error;
515
 
516
        if (!dir || !S_ISDIR(dir->i_mode)) {
517
                printk("nfs_rmdir: inode is NULL or not a directory\n");
518
                iput(dir);
519
                return -ENOENT;
520
        }
521
        if (len > NFS_MAXNAMLEN) {
522
                iput(dir);
523
                return -ENAMETOOLONG;
524
        }
525
        error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), name);
526
        nfs_lookup_cache_remove(dir, NULL, name);
527
        iput(dir);
528
        return error;
529
}
530
 
531
static int nfs_sillyrename(struct inode *dir, const char *name, int len)
532
{
533
        struct inode    *inode;
534
        char            silly[16];
535
        int             slen, ret;
536
 
537
        dir->i_count++;
538
        if (nfs_lookup(dir, name, len, &inode) < 0)
539
                return -EIO;            /* arbitrary */
540
        if (inode->i_count == 1 || NFS_RENAMED_DIR(inode)) {
541
                iput(inode);
542
                return -EIO;
543
        }
544
        slen = sprintf(silly, ".nfs%ld", inode->i_ino);
545
 
546
        if (len == slen && !strncmp(name, silly, len)) {
547
                iput(inode);
548
                return -EIO;            /* DWIM */
549
        }
550
        ret = nfs_proc_rename(NFS_SERVER(dir), NFS_FH(dir), name,
551
                                               NFS_FH(dir), silly, 0);
552
        if (ret >= 0) {
553
                nfs_lookup_cache_remove(dir, NULL, name);
554
                nfs_lookup_cache_remove(dir, NULL, silly);
555
                NFS_RENAMED_DIR(inode) = dir;
556
                dir->i_count++;
557
        }
558
        iput(inode);
559
        return ret;
560
}
561
 
562
void nfs_sillyrename_cleanup(struct inode *inode)
563
{
564
        struct inode    *dir = NFS_RENAMED_DIR(inode);
565
        char            silly[14];
566
        int             error, slen;
567
 
568
        slen = sprintf(silly, ".nfs%ld", inode->i_ino);
569
        error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), silly);
570
        nfs_lookup_cache_remove(dir, NULL, silly);
571
        if (error < 0)
572
                printk("NFS silly_rename cleanup failed (err = %d)\n",
573
                                        -error);
574
        NFS_RENAMED_DIR(inode) = NULL;
575
        iput(dir);
576
}
577
 
578
static int nfs_unlink(struct inode *dir, const char *name, int len)
579
{
580
        int error;
581
 
582
        if (!dir || !S_ISDIR(dir->i_mode)) {
583
                printk("nfs_unlink: inode is NULL or not a directory\n");
584
                iput(dir);
585
                return -ENOENT;
586
        }
587
        if (len > NFS_MAXNAMLEN) {
588
                iput(dir);
589
                return -ENAMETOOLONG;
590
        }
591
        if ((error = nfs_sillyrename(dir, name, len)) < 0) {
592
                error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), name);
593
                nfs_lookup_cache_remove(dir, NULL, name);
594
        }
595
        iput(dir);
596
        return error;
597
}
598
 
599
static int nfs_symlink(struct inode *dir, const char *name, int len,
600
                       const char *symname)
601
{
602
        struct nfs_sattr sattr;
603
        int error;
604
 
605
        if (!dir || !S_ISDIR(dir->i_mode)) {
606
                printk("nfs_symlink: inode is NULL or not a directory\n");
607
                iput(dir);
608
                return -ENOENT;
609
        }
610
        if (len > NFS_MAXNAMLEN) {
611
                iput(dir);
612
                return -ENAMETOOLONG;
613
        }
614
        if (strlen(symname) > NFS_MAXPATHLEN) {
615
                iput(dir);
616
                return -ENAMETOOLONG;
617
        }
618
        sattr.mode = S_IFLNK | S_IRWXUGO; /* SunOS 4.1.2 crashes without this! */
619
        sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
620
        sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
621
        error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir),
622
                name, symname, &sattr);
623
        iput(dir);
624
        return error;
625
}
626
 
627
static int nfs_link(struct inode *oldinode, struct inode *dir,
628
                    const char *name, int len)
629
{
630
        int error;
631
 
632
        if (!oldinode) {
633
                printk("nfs_link: old inode is NULL\n");
634
                iput(oldinode);
635
                iput(dir);
636
                return -ENOENT;
637
        }
638
        if (!dir || !S_ISDIR(dir->i_mode)) {
639
                printk("nfs_link: dir is NULL or not a directory\n");
640
                iput(oldinode);
641
                iput(dir);
642
                return -ENOENT;
643
        }
644
        if (len > NFS_MAXNAMLEN) {
645
                iput(oldinode);
646
                iput(dir);
647
                return -ENAMETOOLONG;
648
        }
649
        error = nfs_proc_link(NFS_SERVER(oldinode), NFS_FH(oldinode),
650
                NFS_FH(dir), name);
651
 
652
        nfs_lookup_cache_remove(dir, oldinode, NULL);
653
        NFS_CACHEINV(oldinode);
654
        iput(oldinode);
655
        iput(dir);
656
        return error;
657
}
658
 
659
static int nfs_rename(struct inode *old_dir, const char *old_name, int old_len,
660
                      struct inode *new_dir, const char *new_name, int new_len,
661
                      int must_be_dir)
662
{
663
        int error;
664
 
665
        if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
666
                printk("nfs_rename: old inode is NULL or not a directory\n");
667
                iput(old_dir);
668
                iput(new_dir);
669
                return -ENOENT;
670
        }
671
        if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
672
                printk("nfs_rename: new inode is NULL or not a directory\n");
673
                iput(old_dir);
674
                iput(new_dir);
675
                return -ENOENT;
676
        }
677
        if (old_len > NFS_MAXNAMLEN || new_len > NFS_MAXNAMLEN) {
678
                iput(old_dir);
679
                iput(new_dir);
680
                return -ENAMETOOLONG;
681
        }
682
        error = nfs_proc_rename(NFS_SERVER(old_dir),
683
                NFS_FH(old_dir), old_name,
684
                NFS_FH(new_dir), new_name,
685
                must_be_dir);
686
 
687
        nfs_lookup_cache_remove(old_dir, NULL, old_name);
688
        nfs_lookup_cache_remove(new_dir, NULL, new_name);
689
        iput(old_dir);
690
        iput(new_dir);
691
        return error;
692
}
693
 
694
/*
695
 * Many nfs protocol calls return the new file attributes after
696
 * an operation.  Here we update the inode to reflect the state
697
 * of the server's inode.
698
 */
699
 
700
void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
701
{
702
        int was_empty;
703
 
704
        if (!inode || !fattr) {
705
                printk("nfs_refresh_inode: inode or fattr is NULL\n");
706
                return;
707
        }
708
        if (inode->i_ino != fattr->fileid) {
709
                printk("nfs_refresh_inode: inode number mismatch\n");
710
                return;
711
        }
712
        was_empty = (inode->i_mode == 0);
713
 
714
        /*
715
         * Some (broken?) NFS servers return 0 as the file type.
716
         * We'll assume that 0 means the file type has not changed.
717
         */
718
        if(!(fattr->mode & S_IFMT)){
719
                inode->i_mode = (inode->i_mode & S_IFMT) |
720
                                (fattr->mode & ~S_IFMT);
721
        }else{
722
                inode->i_mode = fattr->mode;
723
        }
724
        inode->i_nlink = fattr->nlink;
725
        inode->i_uid = fattr->uid;
726
        inode->i_gid = fattr->gid;
727
 
728
        /* Size changed from outside: invalidate caches on next read */
729
        if (inode->i_size != fattr->size)
730
                NFS_CACHEINV(inode);
731
        if (NFS_OLDMTIME(inode) != fattr->mtime.seconds)
732
                NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
733
        inode->i_size = fattr->size;
734
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
735
                inode->i_rdev = to_kdev_t(fattr->rdev);
736
        else
737
                inode->i_rdev = 0;
738
        inode->i_blocks = fattr->blocks;
739
        inode->i_atime = fattr->atime.seconds;
740
        inode->i_mtime = fattr->mtime.seconds;
741
        inode->i_ctime = fattr->ctime.seconds;
742
        if (S_ISREG(inode->i_mode))
743
                inode->i_op = &nfs_file_inode_operations;
744
        else if (S_ISDIR(inode->i_mode))
745
                inode->i_op = &nfs_dir_inode_operations;
746
        else if (S_ISLNK(inode->i_mode))
747
                inode->i_op = &nfs_symlink_inode_operations;
748
        else if (S_ISCHR(inode->i_mode))
749
                inode->i_op = &chrdev_inode_operations;
750
        else if (S_ISBLK(inode->i_mode))
751
                inode->i_op = &blkdev_inode_operations;
752
        else if (S_ISFIFO(inode->i_mode)) {
753
                if (was_empty)
754
                        init_fifo(inode);
755
        } else
756
                inode->i_op = NULL;
757
        nfs_lookup_cache_refresh(inode, fattr);
758
}
759
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.