root/fs/super.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_fs_type
  2. lock_super
  3. free_super
  4. wait_on_super
  5. get_super
  6. put_super
  7. read_super
  8. do_umount
  9. sys_umount
  10. do_mount
  11. sys_mount
  12. mount_root

   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/minix_fs.h>
  13 #include <linux/ext_fs.h>
  14 #include <linux/msdos_fs.h>
  15 #include <linux/kernel.h>
  16 #include <linux/stat.h>
  17 #include <linux/errno.h>
  18 
  19 #include <asm/system.h>
  20 #include <asm/segment.h>
  21 
  22 int sync_dev(int dev);
  23 void wait_for_keypress(void);
  24 
  25 /* set_bit uses setb, as gas doesn't recognize setc */
  26 #define set_bit(bitnr,addr) ({ \
  27 register int __res __asm__("ax"); \
  28 __asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
  29 __res; })
  30 
  31 struct super_block super_block[NR_SUPER];
  32 /* this is initialized in init/main.c */
  33 int ROOT_DEV = 0;
  34 
  35 /* Move into include file later */
  36 
  37 static struct file_system_type file_systems[] = {
  38         {minix_read_super,"minix"},
  39         {ext_read_super,"ext"},
  40         {msdos_read_super,"msdos"},
  41         {NULL,NULL}
  42 };
  43 
  44 /* end of include file */
  45 
  46 struct file_system_type *get_fs_type(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48         int a;
  49         
  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 lock_super(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  57 {
  58         cli();
  59         while (sb->s_lock)
  60                 sleep_on(&(sb->s_wait));
  61         sb->s_lock = 1;
  62         sti();
  63 }
  64 
  65 void free_super(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67         sb->s_lock = 0;
  68         wake_up(&(sb->s_wait));
  69 }
  70 
  71 void wait_on_super(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73         cli();
  74         while (sb->s_lock)
  75                 sleep_on(&(sb->s_wait));
  76         sti();
  77 }
  78 
  79 struct super_block * get_super(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81         struct super_block * s;
  82 
  83         if (!dev)
  84                 return NULL;
  85         s = 0+super_block;
  86         while (s < NR_SUPER+super_block)
  87                 if (s->s_dev == dev) {
  88                         wait_on_super(s);
  89                         if (s->s_dev == dev)
  90                                 return s;
  91                         s = 0+super_block;
  92                 } else
  93                         s++;
  94         return NULL;
  95 }
  96 
  97 void put_super(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99         struct super_block * sb;
 100 
 101         if (dev == ROOT_DEV) {
 102                 printk("root diskette changed: prepare for armageddon\n\r");
 103                 return;
 104         }
 105         if (!(sb = get_super(dev)))
 106                 return;
 107         if (sb->s_covered) {
 108                 printk("Mounted disk changed - tssk, tssk\n\r");
 109                 return;
 110         }
 111         if (sb->s_op && sb->s_op->put_super)
 112                 sb->s_op->put_super(sb);
 113 }
 114 
 115 static struct super_block * read_super(int dev,char *name,int flags,void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         struct super_block * s;
 118         struct file_system_type *type;
 119 
 120         if (!dev)
 121                 return NULL;
 122         check_disk_change(dev);
 123         if (s = get_super(dev))
 124                 return s;
 125         if (!(type=get_fs_type(name))) {
 126                 printk("get fs type failed %s\n",name);
 127                 return NULL;
 128         }
 129         for (s = 0+super_block ;; s++) {
 130                 if (s >= NR_SUPER+super_block)
 131                         return NULL;
 132                 if (!s->s_dev)
 133                         break;
 134         }
 135         s->s_dev = dev;
 136         s->s_flags = flags;
 137         if (!type->read_super(s,data))
 138                 return(NULL);
 139         s->s_dev = dev;
 140         s->s_covered = NULL;
 141         s->s_rd_only = 0;
 142         s->s_dirt = 0;
 143         return(s);
 144 }
 145 
 146 static int do_umount(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148         struct super_block * sb;
 149         struct inode * inode;
 150 
 151         if (dev==ROOT_DEV)
 152                 return -EBUSY;
 153         if (!(sb=get_super(dev)) || !(sb->s_covered))
 154                 return -ENOENT;
 155         if (!sb->s_covered->i_mount)
 156                 printk("Mounted inode has i_mount=0\n");
 157         for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++)
 158                 if (inode->i_dev==dev && inode->i_count)
 159                         if (inode == sb->s_mounted && inode->i_count == 1)
 160                                 continue;
 161                         else
 162                                 return -EBUSY;
 163         sb->s_covered->i_mount=0;
 164         iput(sb->s_covered);
 165         sb->s_covered = NULL;
 166         iput(sb->s_mounted);
 167         sb->s_mounted = NULL;
 168         if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
 169                 sb->s_op->write_super (sb);
 170         put_super(dev);
 171         return 0;
 172 }
 173 
 174 int sys_umount(char * dev_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176         struct inode * inode;
 177         int dev,retval;
 178 
 179         if (!suser())
 180                 return -EPERM;
 181         if (!(inode = namei(dev_name)))
 182                 return -ENOENT;
 183         dev = inode->i_rdev;
 184         if (!S_ISBLK(inode->i_mode)) {
 185                 iput(inode);
 186                 return -ENOTBLK;
 187         }
 188         retval = do_umount(dev);
 189         if (!retval && MAJOR(dev) < MAX_BLKDEV &&
 190             blkdev_fops[MAJOR(dev)]->release)
 191                 blkdev_fops[MAJOR(dev)]->release(inode,NULL);
 192         iput(inode);
 193         if (retval) return retval;
 194         sync_dev(dev);
 195         return 0;
 196 }
 197 
 198 /*
 199  * do_mount() does the actual mounting after sys_mount has done the ugly
 200  * parameter parsing. When enough time has gone by, and everything uses the
 201  * new mount() parameters, sys_mount() can then be cleaned up.
 202  *
 203  * We cannot mount a filesystem if it has active, used, or dirty inodes.
 204  * We also have to flush all inode-data for this device, as the new mount
 205  * might need new info.
 206  */
 207 static int do_mount(int dev, const char * dir, char * type, int flags, void * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 208 {
 209         struct inode * inode, * dir_i;
 210         struct super_block * sb;
 211 
 212         if (!(dir_i = namei(dir)))
 213                 return -ENOENT;
 214         if (dir_i->i_count != 1 || dir_i->i_mount) {
 215                 iput(dir_i);
 216                 return -EBUSY;
 217         }
 218         if (!S_ISDIR(dir_i->i_mode)) {
 219                 iput(dir_i);
 220                 return -EPERM;
 221         }
 222         for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++) {
 223                 if (inode->i_dev != dev)
 224                         continue;
 225                 if (inode->i_count || inode->i_dirt || inode->i_lock) {
 226                         iput(dir_i);
 227                         return -EBUSY;
 228                 }
 229                 inode->i_dev = 0;
 230         }
 231         sb = read_super(dev,type,flags,data);
 232         if (!sb || sb->s_covered) {
 233                 iput(dir_i);
 234                 return -EBUSY;
 235         }
 236         sb->s_flags = flags;
 237         sb->s_covered = dir_i;
 238         dir_i->i_mount = 1;
 239         return 0;               /* we don't iput(dir_i) - see umount */
 240 }
 241 
 242 /*
 243  * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to
 244  * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
 245  *
 246  * data is a (void *) that can point to any structure up to 4095 bytes, which
 247  * can contain arbitrary fs-dependent information (or be NULL).
 248  *
 249  * NOTE! As old versions of mount() didn't use this setup, the flags has to have
 250  * a special 16-bit magic number in the hight word: 0xC0ED. If this magic word
 251  * isn't present, the flags and data info isn't used, as the syscall assumes we
 252  * are talking to an older version that didn't understand them.
 253  */
 254 int sys_mount(char * dev_name, char * dir_name, char * type,
     /* [previous][next][first][last][top][bottom][index][help] */
 255         unsigned long new_flags, void *data)
 256 {
 257         struct inode * inode;
 258         int dev;
 259         int retval = 0;
 260         char tmp[100],*t;
 261         int i;
 262         unsigned long flags = 0;
 263         unsigned long page = 0;
 264 
 265         if (!suser())
 266                 return -EPERM;
 267         if (!(inode = namei(dev_name)))
 268                 return -ENOENT;
 269         dev = inode->i_rdev;
 270         if (!S_ISBLK(inode->i_mode))
 271                 retval = -EPERM;
 272         else if (IS_NODEV(inode))
 273                 retval = -EACCES;
 274         if (!retval && blkdev_fops[MAJOR(dev)]->open)
 275                 retval = blkdev_fops[MAJOR(dev)]->open(inode,NULL);
 276         if (retval) {
 277                 iput(inode);
 278                 return retval;
 279         }
 280         if ((new_flags & 0xffff0000) == 0xC0ED0000) {
 281                 flags = new_flags & 0xffff;
 282                 if (data && (unsigned long) data < TASK_SIZE)
 283                         page = get_free_page(GFP_KERNEL);
 284         }
 285         if (page) {
 286                 i = TASK_SIZE - (unsigned long) data;
 287                 if (i < 0 || i > 4095)
 288                         i = 4095;
 289                 memcpy_fromfs((void *) page,data,i);
 290         }
 291         if (type) {
 292                 for (i = 0 ; i < 100 ; i++)
 293                         if (!(tmp[i] = get_fs_byte(type++)))
 294                                 break;
 295                 t = tmp;
 296         } else
 297                 t = "minix";
 298         retval = do_mount(dev,dir_name,t,flags,(void *) page);
 299         free_page(page);
 300         if (retval && blkdev_fops[MAJOR(dev)]->release)
 301                 blkdev_fops[MAJOR(dev)]->release(inode,NULL);
 302         iput(inode);
 303         return retval;
 304 }
 305 
 306 void mount_root(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 307 {
 308         int i;
 309         struct file_system_type * fs_type = file_systems;
 310         struct super_block * p;
 311         struct inode * mi;
 312 
 313         if (32 != sizeof (struct minix_inode))
 314                 panic("bad i-node size");
 315         for(i=0;i<NR_FILE;i++)
 316                 file_table[i].f_count=0;
 317         if (MAJOR(ROOT_DEV) == 2) {
 318                 printk("Insert root floppy and press ENTER");
 319                 wait_for_keypress();
 320         }
 321         for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) {
 322                 p->s_dev = 0;
 323                 p->s_blocksize = 0;
 324                 p->s_lock = 0;
 325                 p->s_wait = NULL;
 326                 p->s_mounted = p->s_covered = NULL;
 327         }
 328         while (fs_type->read_super && fs_type->name) {
 329                 p = read_super(ROOT_DEV,fs_type->name,0,NULL);
 330                 if (p) {
 331                         mi = p->s_mounted;
 332                         mi->i_count += 3 ;      /* NOTE! it is logically used 4 times, not 1 */
 333                         p->s_covered = mi;
 334                         p->s_flags = 0;
 335                         current->pwd = mi;
 336                         current->root = mi;
 337                         return;
 338                 }
 339                 fs_type++;
 340         }
 341         panic("Unable to mount root");
 342 }

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