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. sys_umount
  9. sys_mount
  10. mount_root

   1 /*
   2  *  linux/fs/super.c
   3  *
   4  *  (C) 1991  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/kernel.h>
  14 #include <asm/system.h>
  15 #include <asm/segment.h>
  16 
  17 #include <errno.h>
  18 #include <sys/stat.h>
  19 
  20 int sync_dev(int dev);
  21 void wait_for_keypress(void);
  22 
  23 /* set_bit uses setb, as gas doesn't recognize setc */
  24 #define set_bit(bitnr,addr) ({ \
  25 register int __res __asm__("ax"); \
  26 __asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
  27 __res; })
  28 
  29 struct super_block super_block[NR_SUPER];
  30 /* this is initialized in init/main.c */
  31 int ROOT_DEV = 0;
  32 
  33 /* Move into include file later */
  34 
  35 static struct file_system_type file_systems[] = {
  36         {minix_read_super,"minix"},
  37         {NULL,NULL}
  38 };
  39 
  40 /* end of include file */
  41 
  42 struct file_system_type *get_fs_type(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44         int a;
  45         
  46         for(a = 0 ; file_systems[a].read_super ; a++)
  47                 if (!strcmp(name,file_systems[a].name))
  48                         return(&file_systems[a]);
  49         return(NULL);
  50 }
  51 
  52 void lock_super(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54         cli();
  55         while (sb->s_lock)
  56                 sleep_on(&(sb->s_wait));
  57         sb->s_lock = 1;
  58         sti();
  59 }
  60 
  61 void free_super(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63         cli();
  64         sb->s_lock = 0;
  65         wake_up(&(sb->s_wait));
  66         sti();
  67 }
  68 
  69 void wait_on_super(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71         cli();
  72         while (sb->s_lock)
  73                 sleep_on(&(sb->s_wait));
  74         sti();
  75 }
  76 
  77 struct super_block * get_super(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  78 {
  79         struct super_block * s;
  80 
  81         if (!dev)
  82                 return NULL;
  83         s = 0+super_block;
  84         while (s < NR_SUPER+super_block)
  85                 if (s->s_dev == dev) {
  86                         wait_on_super(s);
  87                         if (s->s_dev == dev)
  88                                 return s;
  89                         s = 0+super_block;
  90                 } else
  91                         s++;
  92         return NULL;
  93 }
  94 
  95 void put_super(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         struct super_block * sb;
  98 
  99         if (dev == ROOT_DEV) {
 100                 printk("root diskette changed: prepare for armageddon\n\r");
 101                 return;
 102         }
 103         if (!(sb = get_super(dev)))
 104                 return;
 105         if (sb->s_covered) {
 106                 printk("Mounted disk changed - tssk, tssk\n\r");
 107                 return;
 108         }
 109         if (sb->s_op && sb->s_op->put_super)
 110                 sb->s_op->put_super(sb);
 111 }
 112 
 113 static struct super_block * read_super(int dev,char *name,void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 114 {
 115         struct super_block * s;
 116         struct file_system_type *type;
 117 
 118         if (!dev)
 119                 return NULL;
 120         check_disk_change(dev);
 121         if (s = get_super(dev))
 122                 return s;
 123         if (!(type=get_fs_type(name))) {
 124                 printk("get fs type failed %s\n",name);
 125                 return NULL;
 126         }
 127         for (s = 0+super_block ;; s++) {
 128                 if (s >= NR_SUPER+super_block)
 129                         return NULL;
 130                 if (!s->s_dev)
 131                         break;
 132         }
 133         s->s_dev = dev;
 134         if (!type->read_super(s,data))
 135                 return(NULL);
 136         s->s_dev = dev;
 137         s->s_covered = NULL;
 138         s->s_time = 0;
 139         s->s_rd_only = 0;
 140         s->s_dirt = 0;
 141         return(s);
 142 }
 143 
 144 int sys_umount(char * dev_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146         struct inode * inode;
 147         struct super_block * sb;
 148         int dev;
 149 
 150         if (!suser())
 151                 return -EPERM;
 152         if (!(inode = namei(dev_name)))
 153                 return -ENOENT;
 154         dev = inode->i_rdev;
 155         if (!S_ISBLK(inode->i_mode)) {
 156                 iput(inode);
 157                 return -ENOTBLK;
 158         }
 159         iput(inode);
 160         if (dev==ROOT_DEV)
 161                 return -EBUSY;
 162         if (!(sb=get_super(dev)) || !(sb->s_covered))
 163                 return -ENOENT;
 164         if (!sb->s_covered->i_mount)
 165                 printk("Mounted inode has i_mount=0\n");
 166         for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++)
 167                 if (inode->i_dev==dev && inode->i_count)
 168                         if (inode == sb->s_mounted && inode->i_count == 1)
 169                                 continue;
 170                         else
 171                                 return -EBUSY;
 172         sb->s_covered->i_mount=0;
 173         iput(sb->s_covered);
 174         sb->s_covered = NULL;
 175         iput(sb->s_mounted);
 176         sb->s_mounted = NULL;
 177         put_super(dev);
 178         sync_dev(dev);
 179         return 0;
 180 }
 181 
 182 int sys_mount(char * dev_name, char * dir_name, char * type, int rw_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 183 {
 184         struct inode * dev_i, * dir_i;
 185         struct super_block * sb;
 186         int dev;
 187         char tmp[100],*t;
 188         int i;
 189 
 190         if (!suser())
 191                 return -EPERM;
 192         if (!(dev_i = namei(dev_name)))
 193                 return -ENOENT;
 194         dev = dev_i->i_rdev;
 195         if (!S_ISBLK(dev_i->i_mode)) {
 196                 iput(dev_i);
 197                 return -EPERM;
 198         }
 199         iput(dev_i);
 200         if (!(dir_i=namei(dir_name)))
 201                 return -ENOENT;
 202         if (dir_i->i_count != 1 || dir_i->i_ino == MINIX_ROOT_INO) {
 203                 iput(dir_i);
 204                 return -EBUSY;
 205         }
 206         if (!S_ISDIR(dir_i->i_mode)) {
 207                 iput(dir_i);
 208                 return -EPERM;
 209         }
 210         if (dir_i->i_mount) {
 211                 iput(dir_i);
 212                 return -EPERM;
 213         }
 214         if (type) {
 215                 i = 0;
 216                 while (i < 100 && (tmp[i] = get_fs_byte(type++)))
 217                         i++;
 218                 t = tmp;
 219         } else
 220                 t = "minix";
 221         if (!(sb = read_super(dev,t,NULL))) {
 222                 iput(dir_i);
 223                 return -EBUSY;
 224         }
 225         if (sb->s_covered) {
 226                 iput(dir_i);
 227                 return -EBUSY;
 228         }
 229         sb->s_covered = dir_i;
 230         dir_i->i_mount = 1;
 231         dir_i->i_dirt = 1;              /* NOTE! we don't iput(dir_i) */
 232         return 0;                       /* we do that in umount */
 233 }
 234 
 235 void mount_root(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 236 {
 237         int i,free;
 238         struct super_block * p;
 239         struct inode * mi;
 240 
 241         if (32 != sizeof (struct minix_inode))
 242                 panic("bad i-node size");
 243         for(i=0;i<NR_FILE;i++)
 244                 file_table[i].f_count=0;
 245         if (MAJOR(ROOT_DEV) == 2) {
 246                 printk("Insert root floppy and press ENTER");
 247                 wait_for_keypress();
 248         }
 249         for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) {
 250                 p->s_dev = 0;
 251                 p->s_lock = 0;
 252                 p->s_wait = NULL;
 253         }
 254         if (!(p=read_super(ROOT_DEV,"minix",NULL)))
 255                 panic("Unable to mount root");
 256         /*wait_for_keypress();
 257         if (!(mi=iget(ROOT_DEV,MINIX_ROOT_INO)))
 258                 panic("Unable to read root i-node");
 259         wait_for_keypress();*/
 260         mi=p->s_mounted;
 261         mi->i_count += 3 ;      /* NOTE! it is logically used 4 times, not 1 */
 262         p->s_mounted = p->s_covered = mi;
 263         current->pwd = mi;
 264         current->root = mi;
 265         free=0;
 266         i=p->s_nzones;
 267         while (-- i >= 0)
 268                 if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
 269                         free++;
 270         printk("%d/%d free blocks\n\r",free,p->s_nzones);
 271         free=0;
 272         i=p->s_ninodes+1;
 273         while (-- i >= 0)
 274                 if (!set_bit(i&8191,p->s_imap[i>>13]->b_data))
 275                         free++;
 276         printk("%d/%d free inodes\n\r",free,p->s_ninodes);
 277 }

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