root/fs/devices.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_device_list
  2. get_blkfops
  3. get_chrfops
  4. register_chrdev
  5. register_blkdev
  6. unregister_chrdev
  7. unregister_blkdev
  8. check_disk_change
  9. blkdev_open
  10. chrdev_open

   1 /*
   2  *  linux/fs/devices.c
   3  *
   4  * (C) 1993 Matthias Urlichs -- collected common code and tables.
   5  * 
   6  *  Copyright (C) 1991, 1992  Linus Torvalds
   7  */
   8 
   9 #include <linux/fs.h>
  10 #include <linux/major.h>
  11 #include <linux/string.h>
  12 #include <linux/sched.h>
  13 #include <linux/ext_fs.h>
  14 #include <linux/stat.h>
  15 #include <linux/fcntl.h>
  16 #include <linux/errno.h>
  17 
  18 struct device_struct {
  19         const char * name;
  20         struct file_operations * fops;
  21 };
  22 
  23 static struct device_struct chrdevs[MAX_CHRDEV] = {
  24         { NULL, NULL },
  25 };
  26 
  27 static struct device_struct blkdevs[MAX_BLKDEV] = {
  28         { NULL, NULL },
  29 };
  30 
  31 int get_device_list(char * page)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33         int i;
  34         int len;
  35 
  36         len = sprintf(page, "Character devices:\n");
  37         for (i = 0; i < MAX_CHRDEV ; i++) {
  38                 if (chrdevs[i].fops) {
  39                         len += sprintf(page+len, "%2d %s\n", i, chrdevs[i].name);
  40                 }
  41         }
  42         len += sprintf(page+len, "\nBlock devices:\n");
  43         for (i = 0; i < MAX_BLKDEV ; i++) {
  44                 if (blkdevs[i].fops) {
  45                         len += sprintf(page+len, "%2d %s\n", i, blkdevs[i].name);
  46                 }
  47         }
  48         return len;
  49 }
  50 
  51 struct file_operations * get_blkfops(unsigned int major)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53         if (major >= MAX_BLKDEV)
  54                 return NULL;
  55         return blkdevs[major].fops;
  56 }
  57 
  58 struct file_operations * get_chrfops(unsigned int major)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60         if (major >= MAX_CHRDEV)
  61                 return NULL;
  62         return chrdevs[major].fops;
  63 }
  64 
  65 int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67         if (major >= MAX_CHRDEV)
  68                 return -EINVAL;
  69         if (chrdevs[major].fops)
  70                 return -EBUSY;
  71         chrdevs[major].name = name;
  72         chrdevs[major].fops = fops;
  73         return 0;
  74 }
  75 
  76 int register_blkdev(unsigned int major, const char * name, struct file_operations *fops)
     /* [previous][next][first][last][top][bottom][index][help] */
  77 {
  78         if (major >= MAX_BLKDEV)
  79                 return -EINVAL;
  80         if (blkdevs[major].fops)
  81                 return -EBUSY;
  82         blkdevs[major].name = name;
  83         blkdevs[major].fops = fops;
  84         return 0;
  85 }
  86 
  87 int unregister_chrdev(unsigned int major, const char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89         if (major >= MAX_CHRDEV)
  90                 return -EINVAL;
  91         if (!chrdevs[major].fops)
  92                 return -EINVAL;
  93         if (strcmp(chrdevs[major].name, name))
  94                 return -EINVAL;
  95         chrdevs[major].name = NULL;
  96         chrdevs[major].fops = NULL;
  97         return 0;
  98 }
  99 
 100 int unregister_blkdev(unsigned int major, const char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         if (major >= MAX_BLKDEV)
 103                 return -EINVAL;
 104         if (!blkdevs[major].fops)
 105                 return -EINVAL;
 106         if (strcmp(blkdevs[major].name, name))
 107                 return -EINVAL;
 108         blkdevs[major].name = NULL;
 109         blkdevs[major].fops = NULL;
 110         return 0;
 111 }
 112 
 113 /*
 114  * This routine checks whether a removable media has been changed,
 115  * and invalidates all buffer-cache-entries in that case. This
 116  * is a relatively slow routine, so we have to try to minimize using
 117  * it. Thus it is called only upon a 'mount' or 'open'. This
 118  * is the best way of combining speed and utility, I think.
 119  * People changing diskettes in the middle of an operation deserve
 120  * to loose :-)
 121  */
 122 int check_disk_change(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124         int i;
 125         struct file_operations * fops;
 126 
 127         i = MAJOR(dev);
 128         if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
 129                 return 0;
 130         if (fops->check_media_change == NULL)
 131                 return 0;
 132         if (!fops->check_media_change(dev))
 133                 return 0;
 134 
 135         printk("VFS: Disk change detected on device %d/%d\n",
 136                                         MAJOR(dev), MINOR(dev));
 137         for (i=0 ; i<NR_SUPER ; i++)
 138                 if (super_blocks[i].s_dev == dev)
 139                         put_super(super_blocks[i].s_dev);
 140         invalidate_inodes(dev);
 141         invalidate_buffers(dev);
 142 
 143         if (fops->revalidate)
 144                 fops->revalidate(dev);
 145         return 1;
 146 }
 147 
 148 /*
 149  * Called every time a block special file is opened
 150  */
 151 int blkdev_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 152 {
 153         int i;
 154 
 155         i = MAJOR(inode->i_rdev);
 156         if (i >= MAX_BLKDEV || !blkdevs[i].fops)
 157                 return -ENODEV;
 158         filp->f_op = blkdevs[i].fops;
 159         if (filp->f_op->open)
 160                 return filp->f_op->open(inode,filp);
 161         return 0;
 162 }       
 163 
 164 /*
 165  * Dummy default file-operations: the only thing this does
 166  * is contain the open that then fills in the correct operations
 167  * depending on the special file...
 168  */
 169 struct file_operations def_blk_fops = {
 170         NULL,           /* lseek */
 171         NULL,           /* read */
 172         NULL,           /* write */
 173         NULL,           /* readdir */
 174         NULL,           /* select */
 175         NULL,           /* ioctl */
 176         NULL,           /* mmap */
 177         blkdev_open,    /* open */
 178         NULL,           /* release */
 179 };
 180 
 181 struct inode_operations blkdev_inode_operations = {
 182         &def_blk_fops,          /* default file operations */
 183         NULL,                   /* create */
 184         NULL,                   /* lookup */
 185         NULL,                   /* link */
 186         NULL,                   /* unlink */
 187         NULL,                   /* symlink */
 188         NULL,                   /* mkdir */
 189         NULL,                   /* rmdir */
 190         NULL,                   /* mknod */
 191         NULL,                   /* rename */
 192         NULL,                   /* readlink */
 193         NULL,                   /* follow_link */
 194         NULL,                   /* bmap */
 195         NULL,                   /* truncate */
 196         NULL                    /* permission */
 197 };
 198 
 199 /*
 200  * Called every time a character special file is opened
 201  */
 202 int chrdev_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204         int i;
 205 
 206         i = MAJOR(inode->i_rdev);
 207         if (i >= MAX_CHRDEV || !chrdevs[i].fops)
 208                 return -ENODEV;
 209         filp->f_op = chrdevs[i].fops;
 210         if (filp->f_op->open)
 211                 return filp->f_op->open(inode,filp);
 212         return 0;
 213 }
 214 
 215 /*
 216  * Dummy default file-operations: the only thing this does
 217  * is contain the open that then fills in the correct operations
 218  * depending on the special file...
 219  */
 220 struct file_operations def_chr_fops = {
 221         NULL,           /* lseek */
 222         NULL,           /* read */
 223         NULL,           /* write */
 224         NULL,           /* readdir */
 225         NULL,           /* select */
 226         NULL,           /* ioctl */
 227         NULL,           /* mmap */
 228         chrdev_open,    /* open */
 229         NULL,           /* release */
 230 };
 231 
 232 struct inode_operations chrdev_inode_operations = {
 233         &def_chr_fops,          /* default file operations */
 234         NULL,                   /* create */
 235         NULL,                   /* lookup */
 236         NULL,                   /* link */
 237         NULL,                   /* unlink */
 238         NULL,                   /* symlink */
 239         NULL,                   /* mkdir */
 240         NULL,                   /* rmdir */
 241         NULL,                   /* mknod */
 242         NULL,                   /* rename */
 243         NULL,                   /* readlink */
 244         NULL,                   /* follow_link */
 245         NULL,                   /* bmap */
 246         NULL,                   /* truncate */
 247         NULL                    /* permission */
 248 };

/* [previous][next][first][last][top][bottom][index][help] */