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

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