~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/proc/generic.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  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 orig)
142 {
143     switch (orig) {
144     case 0:
145         if (offset < 0)
146             return -EINVAL;    
147         file->f_pos = offset;
148         return(file->f_pos);
149     case 1:
150         if (offset + file->f_pos < 0)
151             return -EINVAL;    
152         file->f_pos += offset;
153         return(file->f_pos);
154     case 2:
155         return(-EINVAL);
156     default:
157         return(-EINVAL);
158     }
159 }
160 
161 /*
162  * This function parses a name such as "tty/driver/serial", and
163  * returns the struct proc_dir_entry for "/proc/tty/driver", and
164  * returns "serial" in residual.
165  */
166 static int xlate_proc_name(const char *name,
167                            struct proc_dir_entry **ret, const char **residual)
168 {
169         const char              *cp = name, *next;
170         struct proc_dir_entry   *de;
171         int                     len;
172 
173         de = &proc_root;
174         while (1) {
175                 next = strchr(cp, '/');
176                 if (!next)
177                         break;
178 
179                 len = next - cp;
180                 for (de = de->subdir; de ; de = de->next) {
181                         if (proc_match(len, cp, de))
182                                 break;
183                 }
184                 if (!de)
185                         return -ENOENT;
186                 cp += len + 1;
187         }
188         *residual = cp;
189         *ret = de;
190         return 0;
191 }
192 
193 static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8];
194 
195 static int make_inode_number(void)
196 {
197         int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
198         if (i<0 || i>=PROC_NDYNAMIC) 
199                 return -1;
200         set_bit(i, (void *) proc_alloc_map);
201         return PROC_DYNAMIC_FIRST + i;
202 }
203 
204 static int proc_readlink(struct dentry *dentry, char *buffer, int buflen)
205 {
206         char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data;
207         return vfs_readlink(dentry, buffer, buflen, s);
208 }
209 
210 static int proc_follow_link(struct dentry *dentry, struct nameidata *nd)
211 {
212         char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data;
213         return vfs_follow_link(nd, s);
214 }
215 
216 static struct inode_operations proc_link_inode_operations = {
217         readlink:       proc_readlink,
218         follow_link:    proc_follow_link,
219 };
220 
221 /*
222  * As some entries in /proc are volatile, we want to 
223  * get rid of unused dentries.  This could be made 
224  * smarter: we could keep a "volatile" flag in the 
225  * inode to indicate which ones to keep.
226  */
227 static int proc_delete_dentry(struct dentry * dentry)
228 {
229         return 1;
230 }
231 
232 static struct dentry_operations proc_dentry_operations =
233 {
234         d_delete:       proc_delete_dentry,
235 };
236 
237 /*
238  * Don't create negative dentries here, return -ENOENT by hand
239  * instead.
240  */
241 struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry)
242 {
243         struct inode *inode;
244         struct proc_dir_entry * de;
245         int error;
246 
247         error = -ENOENT;
248         inode = NULL;
249         de = (struct proc_dir_entry *) dir->u.generic_ip;
250         if (de) {
251                 for (de = de->subdir; de ; de = de->next) {
252                         if (!de || !de->low_ino)
253                                 continue;
254                         if (de->namelen != dentry->d_name.len)
255                                 continue;
256                         if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
257                                 int ino = de->low_ino;
258                                 error = -EINVAL;
259                                 inode = proc_get_inode(dir->i_sb, ino, de);
260                                 break;
261                         }
262                 }
263         }
264 
265         if (inode) {
266                 dentry->d_op = &proc_dentry_operations;
267                 d_add(dentry, inode);
268                 return NULL;
269         }
270         return ERR_PTR(error);
271 }
272 
273 /*
274  * This returns non-zero if at EOF, so that the /proc
275  * root directory can use this and check if it should
276  * continue with the <pid> entries..
277  *
278  * Note that the VFS-layer doesn't care about the return
279  * value of the readdir() call, as long as it's non-negative
280  * for success..
281  */
282 int proc_readdir(struct file * filp,
283         void * dirent, filldir_t filldir)
284 {
285         struct proc_dir_entry * de;
286         unsigned int ino;
287         int i;
288         struct inode *inode = filp->f_dentry->d_inode;
289 
290         ino = inode->i_ino;
291         de = (struct proc_dir_entry *) inode->u.generic_ip;
292         if (!de)
293                 return -EINVAL;
294         i = filp->f_pos;
295         switch (i) {
296                 case 0:
297                         if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
298                                 return 0;
299                         i++;
300                         filp->f_pos++;
301                         /* fall through */
302                 case 1:
303                         if (filldir(dirent, "..", 2, i,
304                                     filp->f_dentry->d_parent->d_inode->i_ino,
305                                     DT_DIR) < 0)
306                                 return 0;
307                         i++;
308                         filp->f_pos++;
309                         /* fall through */
310                 default:
311                         de = de->subdir;
312                         i -= 2;
313                         for (;;) {
314                                 if (!de)
315                                         return 1;
316                                 if (!i)
317                                         break;
318                                 de = de->next;
319                                 i--;
320                         }
321 
322                         do {
323                                 if (filldir(dirent, de->name, de->namelen, filp->f_pos,
324                                             de->low_ino, de->mode >> 12) < 0)
325                                         return 0;
326                                 filp->f_pos++;
327                                 de = de->next;
328                         } while (de);
329         }
330         return 1;
331 }
332 
333 /*
334  * These are the generic /proc directory operations. They
335  * use the in-memory "struct proc_dir_entry" tree to parse
336  * the /proc directory.
337  */
338 static struct file_operations proc_dir_operations = {
339         read:                   generic_read_dir,
340         readdir:                proc_readdir,
341 };
342 
343 /*
344  * proc directories can do almost nothing..
345  */
346 static struct inode_operations proc_dir_inode_operations = {
347         lookup:         proc_lookup,
348 };
349 
350 static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
351 {
352         int     i;
353         
354         i = make_inode_number();
355         if (i < 0)
356                 return -EAGAIN;
357         dp->low_ino = i;
358         dp->next = dir->subdir;
359         dp->parent = dir;
360         dir->subdir = dp;
361         if (S_ISDIR(dp->mode)) {
362                 if (dp->proc_iops == NULL) {
363                         dp->proc_fops = &proc_dir_operations;
364                         dp->proc_iops = &proc_dir_inode_operations;
365                 }
366                 dir->nlink++;
367         } else if (S_ISLNK(dp->mode)) {
368                 if (dp->proc_iops == NULL)
369                         dp->proc_iops = &proc_link_inode_operations;
370         } else if (S_ISREG(dp->mode)) {
371                 if (dp->proc_fops == NULL)
372                         dp->proc_fops = &proc_file_operations;
373         }
374         return 0;
375 }
376 
377 /*
378  * Kill an inode that got unregistered..
379  */
380 static void proc_kill_inodes(struct proc_dir_entry *de)
381 {
382         struct list_head *p;
383         struct super_block *sb = proc_mnt->mnt_sb;
384 
385         /*
386          * Actually it's a partial revoke().
387          */
388         file_list_lock();
389         for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
390                 struct file * filp = list_entry(p, struct file, f_list);
391                 struct dentry * dentry;
392                 struct inode * inode;
393 
394                 dentry = filp->f_dentry;
395                 if (!dentry)
396                         continue;
397                 if (dentry->d_op != &proc_dentry_operations)
398                         continue;
399                 inode = dentry->d_inode;
400                 if (inode->u.generic_ip != de)
401                         continue;
402                 fops_put(filp->f_op);
403                 filp->f_op = NULL;
404         }
405         file_list_unlock();
406 }
407 
408 struct proc_dir_entry *proc_symlink(const char *name,
409                 struct proc_dir_entry *parent, const char *dest)
410 {
411         struct proc_dir_entry *ent = NULL;
412         const char *fn = name;
413         int len;
414 
415         if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
416                 goto out;
417         len = strlen(fn);
418 
419         ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
420         if (!ent)
421                 goto out;
422         memset(ent, 0, sizeof(struct proc_dir_entry));
423         memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
424         ent->name = ((char *) ent) + sizeof(*ent);
425         ent->namelen = len;
426         ent->nlink = 1;
427         ent->mode = S_IFLNK|S_IRUGO|S_IWUGO|S_IXUGO;
428         ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
429         if (!ent->data) {
430                 kfree(ent);
431                 goto out;
432         }
433         strcpy((char*)ent->data,dest);
434 
435         proc_register(parent, ent);
436         
437 out:
438         return ent;
439 }
440 
441 struct proc_dir_entry *proc_mknod(const char *name, mode_t mode,
442                 struct proc_dir_entry *parent, kdev_t rdev)
443 {
444         struct proc_dir_entry *ent = NULL;
445         const char *fn = name;
446         int len;
447 
448         if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
449                 goto out;
450         len = strlen(fn);
451 
452         ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
453         if (!ent)
454                 goto out;
455         memset(ent, 0, sizeof(struct proc_dir_entry));
456         memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
457         ent->name = ((char *) ent) + sizeof(*ent);
458         ent->namelen = len;
459         ent->nlink = 1;
460         ent->mode = mode;
461         ent->rdev = rdev;
462 
463         proc_register(parent, ent);
464         
465 out:
466         return ent;
467 }
468 
469 struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
470 {
471         struct proc_dir_entry *ent = NULL;
472         const char *fn = name;
473         int len;
474 
475         if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
476                 goto out;
477         len = strlen(fn);
478 
479         ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
480         if (!ent)
481                 goto out;
482         memset(ent, 0, sizeof(struct proc_dir_entry));
483         memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
484         ent->name = ((char *) ent) + sizeof(*ent);
485         ent->namelen = len;
486         ent->proc_fops = &proc_dir_operations;
487         ent->proc_iops = &proc_dir_inode_operations;
488         ent->nlink = 2;
489         ent->mode = S_IFDIR | S_IRUGO | S_IXUGO;
490 
491         proc_register(parent, ent);
492         
493 out:
494         return ent;
495 }
496 
497 struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
498                                          struct proc_dir_entry *parent)
499 {
500         struct proc_dir_entry *ent = NULL;
501         const char *fn = name;
502         int len;
503 
504         if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
505                 goto out;
506         len = strlen(fn);
507 
508         ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
509         if (!ent)
510                 goto out;
511         memset(ent, 0, sizeof(struct proc_dir_entry));
512         memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
513         ent->name = ((char *) ent) + sizeof(*ent);
514         ent->namelen = len;
515 
516         if (S_ISDIR(mode)) {
517                 if ((mode & S_IALLUGO) == 0)
518                 mode |= S_IRUGO | S_IXUGO;
519                 ent->proc_fops = &proc_dir_operations;
520                 ent->proc_iops = &proc_dir_inode_operations;
521                 ent->nlink = 2;
522         } else {
523                 if ((mode & S_IFMT) == 0)
524                         mode |= S_IFREG;
525                 if ((mode & S_IALLUGO) == 0)
526                         mode |= S_IRUGO;
527                 ent->nlink = 1;
528         }
529         ent->mode = mode;
530 
531         proc_register(parent, ent);
532         
533 out:
534         return ent;
535 }
536 
537 void free_proc_entry(struct proc_dir_entry *de)
538 {
539         int ino = de->low_ino;
540 
541         if (ino < PROC_DYNAMIC_FIRST ||
542             ino >= PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
543                 return;
544         if (S_ISLNK(de->mode) && de->data)
545                 kfree(de->data);
546         kfree(de);
547 }
548 
549 /*
550  * Remove a /proc entry and free it if it's not currently in use.
551  * If it is in use, we set the 'deleted' flag.
552  */
553 void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
554 {
555         struct proc_dir_entry **p;
556         struct proc_dir_entry *de;
557         const char *fn = name;
558         int len;
559 
560         if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
561                 goto out;
562         len = strlen(fn);
563         for (p = &parent->subdir; *p; p=&(*p)->next ) {
564                 if (!proc_match(len, fn, *p))
565                         continue;
566                 de = *p;
567                 *p = de->next;
568                 de->next = NULL;
569                 if (S_ISDIR(de->mode))
570                         parent->nlink--;
571                 clear_bit(de->low_ino-PROC_DYNAMIC_FIRST,
572                                 (void *) proc_alloc_map);
573                 proc_kill_inodes(de);
574                 de->nlink = 0;
575                 if (!atomic_read(&de->count))
576                         free_proc_entry(de);
577                 else {
578                         de->deleted = 1;
579                         printk("remove_proc_entry: %s/%s busy, count=%d\n",
580                                 parent->name, de->name, atomic_read(&de->count));
581                 }
582                 break;
583         }
584 out:
585         return;
586 }
587 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.