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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [proc/] [generic.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * proc/fs/generic.c --- generic routines for the proc-fs
3
 *
4
 * This file contains generic proc-fs routines for handling
5
 * directories and files.
6
 *
7
 * Copyright (C) 1991, 1992 Linus Torvalds.
8
 * Copyright (C) 1997 Theodore Ts'o
9
 */
10
 
11
#include <asm/uaccess.h>
12
 
13
#include <linux/errno.h>
14
#include <linux/sched.h>
15
#include <linux/proc_fs.h>
16
#include <linux/stat.h>
17
#define __NO_VERSION__
18
#include <linux/module.h>
19
#include <asm/bitops.h>
20
 
21
static ssize_t proc_file_read(struct file * file, char * buf,
22
                              size_t nbytes, loff_t *ppos);
23
static ssize_t proc_file_write(struct file * file, const char * buffer,
24
                               size_t count, loff_t *ppos);
25
static loff_t proc_file_lseek(struct file *, loff_t, int);
26
 
27
int proc_match(int len, const char *name,struct proc_dir_entry * de)
28
{
29
        if (!de || !de->low_ino)
30
                return 0;
31
        if (de->namelen != len)
32
                return 0;
33
        return !memcmp(name, de->name, len);
34
}
35
 
36
static struct file_operations proc_file_operations = {
37
        llseek:         proc_file_lseek,
38
        read:           proc_file_read,
39
        write:          proc_file_write,
40
};
41
 
42
#ifndef MIN
43
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
44
#endif
45
 
46
/* buffer size is one page but our output routines use some slack for overruns */
47
#define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
48
 
49
static ssize_t
50
proc_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
51
{
52
        struct inode * inode = file->f_dentry->d_inode;
53
        char    *page;
54
        ssize_t retval=0;
55
        int     eof=0;
56
        ssize_t n, count;
57
        char    *start;
58
        struct proc_dir_entry * dp;
59
 
60
        dp = (struct proc_dir_entry *) inode->u.generic_ip;
61
        if (!(page = (char*) __get_free_page(GFP_KERNEL)))
62
                return -ENOMEM;
63
 
64
        while ((nbytes > 0) && !eof)
65
        {
66
                count = MIN(PROC_BLOCK_SIZE, nbytes);
67
 
68
                start = NULL;
69
                if (dp->get_info) {
70
                        /*
71
                         * Handle backwards compatibility with the old net
72
                         * routines.
73
                         */
74
                        n = dp->get_info(page, &start, *ppos, count);
75
                        if (n < count)
76
                                eof = 1;
77
                } else if (dp->read_proc) {
78
                        n = dp->read_proc(page, &start, *ppos,
79
                                          count, &eof, dp->data);
80
                } else
81
                        break;
82
 
83
                if (!start) {
84
                        /*
85
                         * For proc files that are less than 4k
86
                         */
87
                        start = page + *ppos;
88
                        n -= *ppos;
89
                        if (n <= 0)
90
                                break;
91
                        if (n > count)
92
                                n = count;
93
                }
94
                if (n == 0)
95
                        break;  /* End of file */
96
                if (n < 0) {
97
                        if (retval == 0)
98
                                retval = n;
99
                        break;
100
                }
101
 
102
                /* This is a hack to allow mangling of file pos independent
103
                 * of actual bytes read.  Simply place the data at page,
104
                 * return the bytes, and set `start' to the desired offset
105
                 * as an unsigned int. - Paul.Russell@rustcorp.com.au
106
                 */
107
                n -= copy_to_user(buf, start < page ? page : start, n);
108
                if (n == 0) {
109
                        if (retval == 0)
110
                                retval = -EFAULT;
111
                        break;
112
                }
113
 
114
                *ppos += start < page ? (long)start : n; /* Move down the file */
115
                nbytes -= n;
116
                buf += n;
117
                retval += n;
118
        }
119
        free_page((unsigned long) page);
120
        return retval;
121
}
122
 
123
static ssize_t
124
proc_file_write(struct file * file, const char * buffer,
125
                size_t count, loff_t *ppos)
126
{
127
        struct inode *inode = file->f_dentry->d_inode;
128
        struct proc_dir_entry * dp;
129
 
130
        dp = (struct proc_dir_entry *) inode->u.generic_ip;
131
 
132
        if (!dp->write_proc)
133
                return -EIO;
134
 
135
        /* FIXME: does this routine need ppos?  probably... */
136
        return dp->write_proc(file, buffer, count, dp->data);
137
}
138
 
139
 
140
static loff_t
141
proc_file_lseek(struct file * file, loff_t offset, int origin)
142
{
143
        long long retval;
144
 
145
        switch (origin) {
146
                case 2:
147
                        offset += file->f_dentry->d_inode->i_size;
148
                        break;
149
                case 1:
150
                        offset += file->f_pos;
151
        }
152
        retval = -EINVAL;
153
        if (offset>=0 && (unsigned long long)offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) {
154
                if (offset != file->f_pos) {
155
                        file->f_pos = offset;
156
                        file->f_reada = 0;
157
                }
158
                retval = offset;
159
        }
160
        /* RED-PEN user can fake an error here by setting offset to >=-4095 && <0  */
161
        return retval;
162
}
163
 
164
/*
165
 * This function parses a name such as "tty/driver/serial", and
166
 * returns the struct proc_dir_entry for "/proc/tty/driver", and
167
 * returns "serial" in residual.
168
 */
169
static int xlate_proc_name(const char *name,
170
                           struct proc_dir_entry **ret, const char **residual)
171
{
172
        const char              *cp = name, *next;
173
        struct proc_dir_entry   *de;
174
        int                     len;
175
 
176
        de = &proc_root;
177
        while (1) {
178
                next = strchr(cp, '/');
179
                if (!next)
180
                        break;
181
 
182
                len = next - cp;
183
                for (de = de->subdir; de ; de = de->next) {
184
                        if (proc_match(len, cp, de))
185
                                break;
186
                }
187
                if (!de)
188
                        return -ENOENT;
189
                cp += len + 1;
190
        }
191
        *residual = cp;
192
        *ret = de;
193
        return 0;
194
}
195
 
196
static unsigned long proc_alloc_map[(PROC_NDYNAMIC + BITS_PER_LONG - 1) / BITS_PER_LONG];
197
 
198
spinlock_t proc_alloc_map_lock = SPIN_LOCK_UNLOCKED;
199
 
200
static int make_inode_number(void)
201
{
202
        int i;
203
        spin_lock(&proc_alloc_map_lock);
204
        i = find_first_zero_bit(proc_alloc_map, PROC_NDYNAMIC);
205
        if (i < 0 || i >= PROC_NDYNAMIC) {
206
                i = -1;
207
                goto out;
208
        }
209
        set_bit(i, proc_alloc_map);
210
        i += PROC_DYNAMIC_FIRST;
211
out:
212
        spin_unlock(&proc_alloc_map_lock);
213
        return i;
214
}
215
 
216
static int proc_readlink(struct dentry *dentry, char *buffer, int buflen)
217
{
218
        char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data;
219
        return vfs_readlink(dentry, buffer, buflen, s);
220
}
221
 
222
static int proc_follow_link(struct dentry *dentry, struct nameidata *nd)
223
{
224
        char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data;
225
        return vfs_follow_link(nd, s);
226
}
227
 
228
static struct inode_operations proc_link_inode_operations = {
229
        readlink:       proc_readlink,
230
        follow_link:    proc_follow_link,
231
};
232
 
233
/*
234
 * As some entries in /proc are volatile, we want to
235
 * get rid of unused dentries.  This could be made
236
 * smarter: we could keep a "volatile" flag in the
237
 * inode to indicate which ones to keep.
238
 */
239
static int proc_delete_dentry(struct dentry * dentry)
240
{
241
        return 1;
242
}
243
 
244
static struct dentry_operations proc_dentry_operations =
245
{
246
        d_delete:       proc_delete_dentry,
247
};
248
 
249
/*
250
 * Don't create negative dentries here, return -ENOENT by hand
251
 * instead.
252
 */
253
struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry)
254
{
255
        struct inode *inode;
256
        struct proc_dir_entry * de;
257
        int error;
258
 
259
        error = -ENOENT;
260
        inode = NULL;
261
        de = (struct proc_dir_entry *) dir->u.generic_ip;
262
        if (de) {
263
                for (de = de->subdir; de ; de = de->next) {
264
                        if (!de || !de->low_ino)
265
                                continue;
266
                        if (de->namelen != dentry->d_name.len)
267
                                continue;
268
                        if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
269
                                int ino = de->low_ino;
270
                                error = -EINVAL;
271
                                inode = proc_get_inode(dir->i_sb, ino, de);
272
                                break;
273
                        }
274
                }
275
        }
276
 
277
        if (inode) {
278
                dentry->d_op = &proc_dentry_operations;
279
                d_add(dentry, inode);
280
                return NULL;
281
        }
282
        return ERR_PTR(error);
283
}
284
 
285
/*
286
 * This returns non-zero if at EOF, so that the /proc
287
 * root directory can use this and check if it should
288
 * continue with the <pid> entries..
289
 *
290
 * Note that the VFS-layer doesn't care about the return
291
 * value of the readdir() call, as long as it's non-negative
292
 * for success..
293
 */
294
int proc_readdir(struct file * filp,
295
        void * dirent, filldir_t filldir)
296
{
297
        struct proc_dir_entry * de;
298
        unsigned int ino;
299
        int i;
300
        struct inode *inode = filp->f_dentry->d_inode;
301
 
302
        ino = inode->i_ino;
303
        de = (struct proc_dir_entry *) inode->u.generic_ip;
304
        if (!de)
305
                return -EINVAL;
306
        i = filp->f_pos;
307
        switch (i) {
308
                case 0:
309
                        if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
310
                                return 0;
311
                        i++;
312
                        filp->f_pos++;
313
                        /* fall through */
314
                case 1:
315
                        if (filldir(dirent, "..", 2, i,
316
                                    filp->f_dentry->d_parent->d_inode->i_ino,
317
                                    DT_DIR) < 0)
318
                                return 0;
319
                        i++;
320
                        filp->f_pos++;
321
                        /* fall through */
322
                default:
323
                        de = de->subdir;
324
                        i -= 2;
325
                        for (;;) {
326
                                if (!de)
327
                                        return 1;
328
                                if (!i)
329
                                        break;
330
                                de = de->next;
331
                                i--;
332
                        }
333
 
334
                        do {
335
                                if (filldir(dirent, de->name, de->namelen, filp->f_pos,
336
                                            de->low_ino, de->mode >> 12) < 0)
337
                                        return 0;
338
                                filp->f_pos++;
339
                                de = de->next;
340
                        } while (de);
341
        }
342
        return 1;
343
}
344
 
345
/*
346
 * These are the generic /proc directory operations. They
347
 * use the in-memory "struct proc_dir_entry" tree to parse
348
 * the /proc directory.
349
 */
350
static struct file_operations proc_dir_operations = {
351
        read:                   generic_read_dir,
352
        readdir:                proc_readdir,
353
};
354
 
355
/*
356
 * proc directories can do almost nothing..
357
 */
358
static struct inode_operations proc_dir_inode_operations = {
359
        lookup:         proc_lookup,
360
};
361
 
362
static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
363
{
364
        int     i;
365
 
366
        i = make_inode_number();
367
        if (i < 0)
368
                return -EAGAIN;
369
        dp->low_ino = i;
370
        dp->next = dir->subdir;
371
        dp->parent = dir;
372
        dir->subdir = dp;
373
        if (S_ISDIR(dp->mode)) {
374
                if (dp->proc_iops == NULL) {
375
                        dp->proc_fops = &proc_dir_operations;
376
                        dp->proc_iops = &proc_dir_inode_operations;
377
                }
378
                dir->nlink++;
379
        } else if (S_ISLNK(dp->mode)) {
380
                if (dp->proc_iops == NULL)
381
                        dp->proc_iops = &proc_link_inode_operations;
382
        } else if (S_ISREG(dp->mode)) {
383
                if (dp->proc_fops == NULL)
384
                        dp->proc_fops = &proc_file_operations;
385
        }
386
        return 0;
387
}
388
 
389
/*
390
 * Kill an inode that got unregistered..
391
 */
392
static void proc_kill_inodes(struct proc_dir_entry *de)
393
{
394
        struct list_head *p;
395
        struct super_block *sb = proc_mnt->mnt_sb;
396
 
397
        /*
398
         * Actually it's a partial revoke().
399
         */
400
        file_list_lock();
401
        for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
402
                struct file * filp = list_entry(p, struct file, f_list);
403
                struct dentry * dentry = filp->f_dentry;
404
                struct inode * inode;
405
                struct file_operations *fops;
406
 
407
                if (dentry->d_op != &proc_dentry_operations)
408
                        continue;
409
                inode = dentry->d_inode;
410
                if (inode->u.generic_ip != de)
411
                        continue;
412
                fops = filp->f_op;
413
                filp->f_op = NULL;
414
                fops_put(fops);
415
        }
416
        file_list_unlock();
417
}
418
 
419
static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent,
420
                                          const char *name,
421
                                          mode_t mode,
422
                                          nlink_t nlink)
423
{
424
        struct proc_dir_entry *ent = NULL;
425
        const char *fn = name;
426
        int len;
427
 
428
        /* make sure name is valid */
429
        if (!name || !strlen(name)) goto out;
430
 
431
        if (!(*parent) && xlate_proc_name(name, parent, &fn) != 0)
432
                goto out;
433
        len = strlen(fn);
434
 
435
        ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
436
        if (!ent) goto out;
437
 
438
        memset(ent, 0, sizeof(struct proc_dir_entry));
439
        memcpy(((char *) ent) + sizeof(struct proc_dir_entry), fn, len + 1);
440
        ent->name = ((char *) ent) + sizeof(*ent);
441
        ent->namelen = len;
442
        ent->mode = mode;
443
        ent->nlink = nlink;
444
 out:
445
        return ent;
446
}
447
 
448
struct proc_dir_entry *proc_symlink(const char *name,
449
                struct proc_dir_entry *parent, const char *dest)
450
{
451
        struct proc_dir_entry *ent;
452
 
453
        ent = proc_create(&parent,name,
454
                          (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
455
 
456
        if (ent) {
457
                ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
458
                if (ent->data) {
459
                        strcpy((char*)ent->data,dest);
460
                        if (proc_register(parent, ent) < 0) {
461
                                kfree(ent->data);
462
                                kfree(ent);
463
                                ent = NULL;
464
                        }
465
                } else {
466
                        kfree(ent);
467
                        ent = NULL;
468
                }
469
        }
470
        return ent;
471
}
472
 
473
struct proc_dir_entry *proc_mknod(const char *name, mode_t mode,
474
                struct proc_dir_entry *parent, kdev_t rdev)
475
{
476
        struct proc_dir_entry *ent;
477
 
478
        ent = proc_create(&parent,name,mode,1);
479
        if (ent) {
480
                ent->rdev = rdev;
481
                if (proc_register(parent, ent) < 0) {
482
                        kfree(ent);
483
                        ent = NULL;
484
                }
485
        }
486
        return ent;
487
}
488
 
489
struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
490
{
491
        struct proc_dir_entry *ent;
492
 
493
        ent = proc_create(&parent,name,
494
                          (S_IFDIR | S_IRUGO | S_IXUGO),2);
495
        if (ent) {
496
                ent->proc_fops = &proc_dir_operations;
497
                ent->proc_iops = &proc_dir_inode_operations;
498
 
499
                if (proc_register(parent, ent) < 0) {
500
                        kfree(ent);
501
                        ent = NULL;
502
                }
503
        }
504
        return ent;
505
}
506
 
507
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
508
                                         struct proc_dir_entry *parent)
509
{
510
        struct proc_dir_entry *ent;
511
        nlink_t nlink;
512
 
513
        if (S_ISDIR(mode)) {
514
                if ((mode & S_IALLUGO) == 0)
515
                        mode |= S_IRUGO | S_IXUGO;
516
                nlink = 2;
517
        } else {
518
                if ((mode & S_IFMT) == 0)
519
                        mode |= S_IFREG;
520
                if ((mode & S_IALLUGO) == 0)
521
                        mode |= S_IRUGO;
522
                nlink = 1;
523
        }
524
 
525
        ent = proc_create(&parent,name,mode,nlink);
526
        if (ent) {
527
                if (S_ISDIR(mode)) {
528
                        ent->proc_fops = &proc_dir_operations;
529
                        ent->proc_iops = &proc_dir_inode_operations;
530
                }
531
                if (proc_register(parent, ent) < 0) {
532
                        kfree(ent);
533
                        ent = NULL;
534
                }
535
        }
536
        return ent;
537
}
538
 
539
void free_proc_entry(struct proc_dir_entry *de)
540
{
541
        int ino = de->low_ino;
542
 
543
        if (ino < PROC_DYNAMIC_FIRST ||
544
            ino >= PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
545
                return;
546
        if (S_ISLNK(de->mode) && de->data)
547
                kfree(de->data);
548
        kfree(de);
549
}
550
 
551
/*
552
 * Remove a /proc entry and free it if it's not currently in use.
553
 * If it is in use, we set the 'deleted' flag.
554
 */
555
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
556
{
557
        struct proc_dir_entry **p;
558
        struct proc_dir_entry *de;
559
        const char *fn = name;
560
        int len;
561
 
562
        if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
563
                goto out;
564
        len = strlen(fn);
565
        for (p = &parent->subdir; *p; p=&(*p)->next ) {
566
                if (!proc_match(len, fn, *p))
567
                        continue;
568
                de = *p;
569
                *p = de->next;
570
                de->next = NULL;
571
                if (S_ISDIR(de->mode))
572
                        parent->nlink--;
573
                clear_bit(de->low_ino - PROC_DYNAMIC_FIRST,
574
                          proc_alloc_map);
575
                proc_kill_inodes(de);
576
                de->nlink = 0;
577
                if (!atomic_read(&de->count))
578
                        free_proc_entry(de);
579
                else {
580
                        de->deleted = 1;
581
                        printk("remove_proc_entry: %s/%s busy, count=%d\n",
582
                                parent->name, de->name, atomic_read(&de->count));
583
                }
584
                break;
585
        }
586
out:
587
        return;
588
}

powered by: WebSVN 2.1.0

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