root/fs/super.c

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

DEFINITIONS

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

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