home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / super.c < prev   
Encoding:
C/C++ Source or Header  |  1994-03-01  |  12.2 KB  |  538 lines

  1. /*
  2.  *  linux/fs/super.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. /*
  8.  * super.c contains code to handle the super-block tables.
  9.  */
  10. #include <linux/config.h>
  11. #include <linux/sched.h>
  12. #include <linux/kernel.h>
  13. #include <linux/major.h>
  14. #include <linux/stat.h>
  15. #include <linux/errno.h>
  16. #include <linux/string.h>
  17. #include <linux/locks.h>
  18.  
  19. #include <asm/system.h>
  20. #include <asm/segment.h>
  21.  
  22.  
  23. /*
  24.  * The definition of file_systems that used to be here is now in
  25.  * filesystems.c.  Now super.c contains no fs specific code.  -- jrs
  26.  */
  27.  
  28. extern struct file_system_type file_systems[];
  29. extern struct file_operations * get_blkfops(unsigned int);
  30. extern struct file_operations * get_chrfops(unsigned int);
  31.  
  32. extern void wait_for_keypress(void);
  33. extern void fcntl_init_locks(void);
  34.  
  35. extern int root_mountflags;
  36.  
  37. struct super_block super_blocks[NR_SUPER];
  38.  
  39. static int do_remount_sb(struct super_block *sb, int flags, char * data);
  40.  
  41. /* this is initialized in init/main.c */
  42. dev_t ROOT_DEV = 0;
  43.  
  44. struct file_system_type *get_fs_type(char *name)
  45. {
  46.     int a;
  47.     
  48.     if (!name)
  49.         return &file_systems[0];
  50.     for(a = 0 ; file_systems[a].read_super ; a++)
  51.         if (!strcmp(name,file_systems[a].name))
  52.             return(&file_systems[a]);
  53.     return NULL;
  54. }
  55.  
  56. void __wait_on_super(struct super_block * sb)
  57. {
  58.     struct wait_queue wait = { current, NULL };
  59.  
  60.     add_wait_queue(&sb->s_wait, &wait);
  61. repeat:
  62.     current->state = TASK_UNINTERRUPTIBLE;
  63.     if (sb->s_lock) {
  64.         schedule();
  65.         goto repeat;
  66.     }
  67.     remove_wait_queue(&sb->s_wait, &wait);
  68.     current->state = TASK_RUNNING;
  69. }
  70.  
  71. void sync_supers(dev_t dev)
  72. {
  73.     struct super_block * sb;
  74.  
  75.     for (sb = super_blocks + 0 ; sb < super_blocks + NR_SUPER ; sb++) {
  76.         if (!sb->s_dev)
  77.             continue;
  78.         if (dev && sb->s_dev != dev)
  79.             continue;
  80.         wait_on_super(sb);
  81.         if (!sb->s_dev || !sb->s_dirt)
  82.             continue;
  83.         if (dev && (dev != sb->s_dev))
  84.             continue;
  85.         if (sb->s_op && sb->s_op->write_super)
  86.             sb->s_op->write_super(sb);
  87.     }
  88. }
  89.  
  90. static struct super_block * get_super(dev_t dev)
  91. {
  92.     struct super_block * s;
  93.  
  94.     if (!dev)
  95.         return NULL;
  96.     s = 0+super_blocks;
  97.     while (s < NR_SUPER+super_blocks)
  98.         if (s->s_dev == dev) {
  99.             wait_on_super(s);
  100.             if (s->s_dev == dev)
  101.                 return s;
  102.             s = 0+super_blocks;
  103.         } else
  104.             s++;
  105.     return NULL;
  106. }
  107.  
  108. void put_super(dev_t dev)
  109. {
  110.     struct super_block * sb;
  111.  
  112.     if (dev == ROOT_DEV) {
  113.         printk("VFS: Root device %d/%d: prepare for armageddon\n",
  114.                             MAJOR(dev), MINOR(dev));
  115.         return;
  116.     }
  117.     if (!(sb = get_super(dev)))
  118.         return;
  119.     if (sb->s_covered) {
  120.         printk("VFS: Mounted device %d/%d - tssk, tssk\n",
  121.                         MAJOR(dev), MINOR(dev));
  122.         return;
  123.     }
  124.     if (sb->s_op && sb->s_op->put_super)
  125.         sb->s_op->put_super(sb);
  126. }
  127.  
  128. static struct super_block * read_super(dev_t dev,char *name,int flags,
  129.                        void *data, int silent)
  130. {
  131.     struct super_block * s;
  132.     struct file_system_type *type;
  133.  
  134.     if (!dev)
  135.         return NULL;
  136.     check_disk_change(dev);
  137.     s = get_super(dev);
  138.     if (s)
  139.         return s;
  140.     if (!(type = get_fs_type(name))) {
  141.         printk("VFS: on device %d/%d: get_fs_type(%s) failed\n",
  142.                         MAJOR(dev), MINOR(dev), name);
  143.         return NULL;
  144.     }
  145.     for (s = 0+super_blocks ;; s++) {
  146.         if (s >= NR_SUPER+super_blocks)
  147.             return NULL;
  148.         if (!s->s_dev)
  149.             break;
  150.     }
  151.     s->s_dev = dev;
  152.     s->s_flags = flags;
  153.     if (!type->read_super(s,data, silent)) {
  154.         s->s_dev = 0;
  155.         return NULL;
  156.     }
  157.     s->s_dev = dev;
  158.     s->s_covered = NULL;
  159.     s->s_rd_only = 0;
  160.     s->s_dirt = 0;
  161.     return s;
  162. }
  163.  
  164. /*
  165.  * Unnamed block devices are dummy devices used by virtual
  166.  * filesystems which don't use real block-devices.  -- jrs
  167.  */
  168.  
  169. static char unnamed_dev_in_use[256];
  170.  
  171. static dev_t get_unnamed_dev(void)
  172. {
  173.     static int first_use = 0;
  174.     int i;
  175.  
  176.     if (first_use == 0) {
  177.         first_use = 1;
  178.         memset(unnamed_dev_in_use, 0, sizeof(unnamed_dev_in_use));
  179.         unnamed_dev_in_use[0] = 1; /* minor 0 (nodev) is special */
  180.     }
  181.     for (i = 0; i < sizeof unnamed_dev_in_use/sizeof unnamed_dev_in_use[0]; i++) {
  182.         if (!unnamed_dev_in_use[i]) {
  183.             unnamed_dev_in_use[i] = 1;
  184.             return (UNNAMED_MAJOR << 8) | i;
  185.         }
  186.     }
  187.     return 0;
  188. }
  189.  
  190. static void put_unnamed_dev(dev_t dev)
  191. {
  192.     if (!dev)
  193.         return;
  194.     if (!unnamed_dev_in_use[dev]) {
  195.         printk("VFS: put_unnamed_dev: freeing unused device %d/%d\n",
  196.                             MAJOR(dev), MINOR(dev));
  197.         return;
  198.     }
  199.     unnamed_dev_in_use[dev] = 0;
  200. }
  201.  
  202. static int do_umount(dev_t dev)
  203. {
  204.     struct super_block * sb;
  205.     int retval;
  206.     
  207.     if (dev==ROOT_DEV) {
  208.         /* Special case for "unmounting" root.  We just try to remount
  209.            it readonly, and sync() the device. */
  210.         if (!(sb=get_super(dev)))
  211.             return -ENOENT;
  212.         if (!(sb->s_flags & MS_RDONLY)) {
  213.             fsync_dev(dev);
  214.             retval = do_remount_sb(sb, MS_RDONLY, 0);
  215.             if (retval)
  216.                 return retval;
  217.         }
  218.         return 0;
  219.     }
  220.     if (!(sb=get_super(dev)) || !(sb->s_covered))
  221.         return -ENOENT;
  222.     if (!sb->s_covered->i_mount)
  223.         printk("VFS: umount(%d/%d): mounted inode has i_mount=NULL\n",
  224.                             MAJOR(dev), MINOR(dev));
  225.     if (!fs_may_umount(dev, sb->s_mounted))
  226.         return -EBUSY;
  227.     sb->s_covered->i_mount = NULL;
  228.     iput(sb->s_covered);
  229.     sb->s_covered = NULL;
  230.     iput(sb->s_mounted);
  231.     sb->s_mounted = NULL;
  232.     if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
  233.         sb->s_op->write_super(sb);
  234.     put_super(dev);
  235.     return 0;
  236. }
  237.  
  238. /*
  239.  * Now umount can handle mount points as well as block devices.
  240.  * This is important for filesystems which use unnamed block devices.
  241.  *
  242.  * There is a little kludge here with the dummy_inode.  The current
  243.  * vfs release functions only use the r_dev field in the inode so
  244.  * we give them the info they need without using a real inode.
  245.  * If any other fields are ever needed by any block device release
  246.  * functions, they should be faked here.  -- jrs
  247.  */
  248.  
  249. asmlinkage int sys_umount(char * name)
  250. {
  251.     struct inode * inode;
  252.     dev_t dev;
  253.     int retval;
  254.     struct inode dummy_inode;
  255.     struct file_operations * fops;
  256.  
  257.     if (!suser())
  258.         return -EPERM;
  259.     retval = namei(name,&inode);
  260.     if (retval) {
  261.         retval = lnamei(name,&inode);
  262.         if (retval)
  263.             return retval;
  264.     }
  265.     if (S_ISBLK(inode->i_mode)) {
  266.         dev = inode->i_rdev;
  267.         if (IS_NODEV(inode)) {
  268.             iput(inode);
  269.             return -EACCES;
  270.         }
  271.     } else {
  272.         if (!inode || !inode->i_sb || inode != inode->i_sb->s_mounted) {
  273.             iput(inode);
  274.             return -EINVAL;
  275.         }
  276.         dev = inode->i_sb->s_dev;
  277.         iput(inode);
  278.         memset(&dummy_inode, 0, sizeof(dummy_inode));
  279.         dummy_inode.i_rdev = dev;
  280.         inode = &dummy_inode;
  281.     }
  282.     if (MAJOR(dev) >= MAX_BLKDEV) {
  283.         iput(inode);
  284.         return -ENXIO;
  285.     }
  286.     if (!(retval = do_umount(dev)) && dev != ROOT_DEV) {
  287.         fops = get_blkfops(MAJOR(dev));
  288.         if (fops && fops->release)
  289.             fops->release(inode,NULL);
  290.         if (MAJOR(dev) == UNNAMED_MAJOR)
  291.             put_unnamed_dev(dev);
  292.     }
  293.     if (inode != &dummy_inode)
  294.         iput(inode);
  295.     if (retval)
  296.         return retval;
  297.     fsync_dev(dev);
  298.     return 0;
  299. }
  300.  
  301. /*
  302.  * do_mount() does the actual mounting after sys_mount has done the ugly
  303.  * parameter parsing. When enough time has gone by, and everything uses the
  304.  * new mount() parameters, sys_mount() can then be cleaned up.
  305.  *
  306.  * We cannot mount a filesystem if it has active, used, or dirty inodes.
  307.  * We also have to flush all inode-data for this device, as the new mount
  308.  * might need new info.
  309.  */
  310. static int do_mount(dev_t dev, const char * dir, char * type, int flags, void * data)
  311. {
  312.     struct inode * dir_i;
  313.     struct super_block * sb;
  314.     int error;
  315.  
  316.     error = namei(dir,&dir_i);
  317.     if (error)
  318.         return error;
  319.     if (dir_i->i_count != 1 || dir_i->i_mount) {
  320.         iput(dir_i);
  321.         return -EBUSY;
  322.     }
  323.     if (!S_ISDIR(dir_i->i_mode)) {
  324.         iput(dir_i);
  325.         return -EPERM;
  326.     }
  327.     if (!fs_may_mount(dev)) {
  328.         iput(dir_i);
  329.         return -EBUSY;
  330.     }
  331.     sb = read_super(dev,type,flags,data,0);
  332.     if (!sb || sb->s_covered) {
  333.         iput(dir_i);
  334.         return -EBUSY;
  335.     }
  336.     sb->s_covered = dir_i;
  337.     dir_i->i_mount = sb->s_mounted;
  338.     return 0;        /* we don't iput(dir_i) - see umount */
  339. }
  340.  
  341.  
  342. /*
  343.  * Alters the mount flags of a mounted file system. Only the mount point
  344.  * is used as a reference - file system type and the device are ignored.
  345.  * FS-specific mount options can't be altered by remounting.
  346.  */
  347.  
  348. static int do_remount_sb(struct super_block *sb, int flags, char *data)
  349. {
  350.     int retval;
  351.     
  352.     /* If we are remounting RDONLY, make sure there are no rw files open */
  353.     if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
  354.         if (!fs_may_remount_ro(sb->s_dev))
  355.             return -EBUSY;
  356.     if (sb->s_op && sb->s_op->remount_fs) {
  357.         retval = sb->s_op->remount_fs(sb, &flags, data);
  358.         if (retval)
  359.             return retval;
  360.     }
  361.     sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) |
  362.         (flags & MS_RMT_MASK);
  363.     return 0;
  364. }
  365.  
  366. static int do_remount(const char *dir,int flags,char *data)
  367. {
  368.     struct inode *dir_i;
  369.     int retval;
  370.  
  371.     retval = namei(dir,&dir_i);
  372.     if (retval)
  373.         return retval;
  374.     if (dir_i != dir_i->i_sb->s_mounted) {
  375.         iput(dir_i);
  376.         return -EINVAL;
  377.     }
  378.     retval = do_remount_sb(dir_i->i_sb, flags, data);
  379.     iput(dir_i);
  380.     return retval;
  381. }
  382.  
  383. static int copy_mount_options (const void * data, unsigned long *where)
  384. {
  385.     int i;
  386.     unsigned long page;
  387.     struct vm_area_struct * vma;
  388.  
  389.     *where = 0;
  390.     if (!data)
  391.         return 0;
  392.  
  393.     for (vma = current->mmap ; ; ) {
  394.         if (!vma ||
  395.             (unsigned long) data < vma->vm_start) {
  396.             return -EFAULT;
  397.         }
  398.         if ((unsigned long) data < vma->vm_end)
  399.             break;
  400.         vma = vma->vm_next;
  401.     }
  402.     i = vma->vm_end - (unsigned long) data;
  403.     if (PAGE_SIZE <= (unsigned long) i)
  404.         i = PAGE_SIZE-1;
  405.     if (!(page = __get_free_page(GFP_KERNEL))) {
  406.         return -ENOMEM;
  407.     }
  408.     memcpy_fromfs((void *) page,data,i);
  409.     *where = page;
  410.     return 0;
  411. }
  412.  
  413. /*
  414.  * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to
  415.  * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
  416.  *
  417.  * data is a (void *) that can point to any structure up to
  418.  * PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent
  419.  * information (or be NULL).
  420.  *
  421.  * NOTE! As old versions of mount() didn't use this setup, the flags
  422.  * has to have a special 16-bit magic number in the hight word:
  423.  * 0xC0ED. If this magic word isn't present, the flags and data info
  424.  * isn't used, as the syscall assumes we are talking to an older
  425.  * version that didn't understand them.
  426.  */
  427. asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
  428.     unsigned long new_flags, void * data)
  429. {
  430.     struct file_system_type * fstype;
  431.     struct inode * inode;
  432.     struct file_operations * fops;
  433.     dev_t dev;
  434.     int retval;
  435.     char * t;
  436.     unsigned long flags = 0;
  437.     unsigned long page = 0;
  438.  
  439.     if (!suser())
  440.         return -EPERM;
  441.     if ((new_flags &
  442.          (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) {
  443.         retval = copy_mount_options (data, &page);
  444.         if (retval < 0)
  445.             return retval;
  446.         retval = do_remount(dir_name,
  447.                     new_flags & ~MS_MGC_MSK & ~MS_REMOUNT,
  448.                     (char *) page);
  449.         free_page(page);
  450.         return retval;
  451.     }
  452.     retval = copy_mount_options (type, &page);
  453.     if (retval < 0)
  454.         return retval;
  455.     fstype = get_fs_type((char *) page);
  456.     free_page(page);
  457.     if (!fstype)        
  458.         return -ENODEV;
  459.     t = fstype->name;
  460.     if (fstype->requires_dev) {
  461.         retval = namei(dev_name,&inode);
  462.         if (retval)
  463.             return retval;
  464.         if (!S_ISBLK(inode->i_mode)) {
  465.             iput(inode);
  466.             return -ENOTBLK;
  467.         }
  468.         if (IS_NODEV(inode)) {
  469.             iput(inode);
  470.             return -EACCES;
  471.         }
  472.         dev = inode->i_rdev;
  473.         if (MAJOR(dev) >= MAX_BLKDEV) {
  474.             iput(inode);
  475.             return -ENXIO;
  476.         }
  477.     } else {
  478.         if (!(dev = get_unnamed_dev()))
  479.             return -EMFILE;
  480.         inode = NULL;
  481.     }
  482.     fops = get_blkfops(MAJOR(dev));
  483.     if (fops && fops->open) {
  484.         retval = fops->open(inode,NULL);
  485.         if (retval) {
  486.             iput(inode);
  487.             return retval;
  488.         }
  489.     }
  490.     page = 0;
  491.     if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) {
  492.         flags = new_flags & ~MS_MGC_MSK;
  493.         retval = copy_mount_options(data, &page);
  494.         if (retval < 0) {
  495.             iput(inode);
  496.             return retval;
  497.         }
  498.     }
  499.     retval = do_mount(dev,dir_name,t,flags,(void *) page);
  500.     free_page(page);
  501.     if (retval && fops && fops->release)
  502.         fops->release(inode,NULL);
  503.     iput(inode);
  504.     return retval;
  505. }
  506.  
  507. void mount_root(void)
  508. {
  509.     struct file_system_type * fs_type;
  510.     struct super_block * sb;
  511.     struct inode * inode;
  512.  
  513.     memset(super_blocks, 0, sizeof(super_blocks));
  514.     fcntl_init_locks();
  515.     if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
  516.         printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
  517.         wait_for_keypress();
  518.     }
  519.     for (fs_type = file_systems; fs_type->read_super; fs_type++) {
  520.         if (!fs_type->requires_dev)
  521.             continue;
  522.         sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
  523.         if (sb) {
  524.             inode = sb->s_mounted;
  525.             inode->i_count += 3 ;    /* NOTE! it is logically used 4 times, not 1 */
  526.             sb->s_covered = inode;
  527.             sb->s_flags = root_mountflags;
  528.             current->pwd = inode;
  529.             current->root = inode;
  530.             printk ("VFS: Mounted root (%s filesystem)%s.\n",
  531.                 fs_type->name,
  532.                 (sb->s_flags & MS_RDONLY) ? " readonly" : "");
  533.             return;
  534.         }
  535.     }
  536.     panic("VFS: Unable to mount root");
  537. }
  538.