root/fs/super.c

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

DEFINITIONS

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

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