home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / fs / super.c < prev   
Encoding:
C/C++ Source or Header  |  1994-06-05  |  12.1 KB  |  526 lines

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