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         struct m_inode * inode;
  78         int i;
  79 
  80         if (dev == ROOT_DEV) {
  81                 printk("root diskette changed: prepare for armageddon\n\r");
  82                 return;
  83         }
  84         if (!(sb = get_super(dev)))
  85                 return;
  86         if (sb->s_imount) {
  87                 printk("Mounted disk changed - tssk, tssk\n\r");
  88                 return;
  89         }
  90         lock_super(sb);
  91         sb->s_dev = 0;
  92         for(i=0;i<I_MAP_SLOTS;i++)
  93                 brelse(sb->s_imap[i]);
  94         for(i=0;i<Z_MAP_SLOTS;i++)
  95                 brelse(sb->s_zmap[i]);
  96         free_super(sb);
  97         return;
  98 }
  99 
 100 static struct super_block * read_super(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         struct super_block * s;
 103         struct buffer_head * bh;
 104         int i,block;
 105 
 106         if (!dev)
 107                 return NULL;
 108         check_disk_change(dev);
 109         if (s = get_super(dev))
 110                 return s;
 111         for (s = 0+super_block ;; s++) {
 112                 if (s >= NR_SUPER+super_block)
 113                         return NULL;
 114                 if (!s->s_dev)
 115                         break;
 116         }
 117         s->s_dev = dev;
 118         s->s_isup = NULL;
 119         s->s_imount = NULL;
 120         s->s_time = 0;
 121         s->s_rd_only = 0;
 122         s->s_dirt = 0;
 123         lock_super(s);
 124         if (!(bh = bread(dev,1))) {
 125                 s->s_dev=0;
 126                 free_super(s);
 127                 return NULL;
 128         }
 129         *((struct d_super_block *) s) =
 130                 *((struct d_super_block *) bh->b_data);
 131         brelse(bh);
 132         if (s->s_magic != SUPER_MAGIC) {
 133                 s->s_dev = 0;
 134                 free_super(s);
 135                 return NULL;
 136         }
 137         for (i=0;i<I_MAP_SLOTS;i++)
 138                 s->s_imap[i] = NULL;
 139         for (i=0;i<Z_MAP_SLOTS;i++)
 140                 s->s_zmap[i] = NULL;
 141         block=2;
 142         for (i=0 ; i < s->s_imap_blocks ; i++)
 143                 if (s->s_imap[i]=bread(dev,block))
 144                         block++;
 145                 else
 146                         break;
 147         for (i=0 ; i < s->s_zmap_blocks ; i++)
 148                 if (s->s_zmap[i]=bread(dev,block))
 149                         block++;
 150                 else
 151                         break;
 152         if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
 153                 for(i=0;i<I_MAP_SLOTS;i++)
 154                         brelse(s->s_imap[i]);
 155                 for(i=0;i<Z_MAP_SLOTS;i++)
 156                         brelse(s->s_zmap[i]);
 157                 s->s_dev=0;
 158                 free_super(s);
 159                 return NULL;
 160         }
 161         s->s_imap[0]->b_data[0] |= 1;
 162         s->s_zmap[0]->b_data[0] |= 1;
 163         free_super(s);
 164         return s;
 165 }
 166 
 167 int sys_umount(char * dev_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169         struct m_inode * inode;
 170         struct super_block * sb;
 171         int dev;
 172 
 173         if (!(inode=namei(dev_name)))
 174                 return -ENOENT;
 175         dev = inode->i_zone[0];
 176         if (!S_ISBLK(inode->i_mode)) {
 177                 iput(inode);
 178                 return -ENOTBLK;
 179         }
 180         iput(inode);
 181         if (dev==ROOT_DEV)
 182                 return -EBUSY;
 183         if (!(sb=get_super(dev)) || !(sb->s_imount))
 184                 return -ENOENT;
 185         if (!sb->s_imount->i_mount)
 186                 printk("Mounted inode has i_mount=0\n");
 187         for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++)
 188                 if (inode->i_dev==dev && inode->i_count)
 189                                 return -EBUSY;
 190         sb->s_imount->i_mount=0;
 191         iput(sb->s_imount);
 192         sb->s_imount = NULL;
 193         iput(sb->s_isup);
 194         sb->s_isup = NULL;
 195         put_super(dev);
 196         sync_dev(dev);
 197         return 0;
 198 }
 199 
 200 int sys_mount(char * dev_name, char * dir_name, int rw_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202         struct m_inode * dev_i, * dir_i;
 203         struct super_block * sb;
 204         int dev;
 205 
 206         if (!(dev_i=namei(dev_name)))
 207                 return -ENOENT;
 208         dev = dev_i->i_zone[0];
 209         if (!S_ISBLK(dev_i->i_mode)) {
 210                 iput(dev_i);
 211                 return -EPERM;
 212         }
 213         iput(dev_i);
 214         if (!(dir_i=namei(dir_name)))
 215                 return -ENOENT;
 216         if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO) {
 217                 iput(dir_i);
 218                 return -EBUSY;
 219         }
 220         if (!S_ISDIR(dir_i->i_mode)) {
 221                 iput(dir_i);
 222                 return -EPERM;
 223         }
 224         if (!(sb=read_super(dev))) {
 225                 iput(dir_i);
 226                 return -EBUSY;
 227         }
 228         if (sb->s_imount) {
 229                 iput(dir_i);
 230                 return -EBUSY;
 231         }
 232         if (dir_i->i_mount) {
 233                 iput(dir_i);
 234                 return -EPERM;
 235         }
 236         sb->s_imount=dir_i;
 237         dir_i->i_mount=1;
 238         dir_i->i_dirt=1;                /* NOTE! we don't iput(dir_i) */
 239         return 0;                       /* we do that in umount */
 240 }
 241 
 242 void mount_root(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 243 {
 244         int i,free;
 245         struct super_block * p;
 246         struct m_inode * mi;
 247 
 248         if (32 != sizeof (struct d_inode))
 249                 panic("bad i-node size");
 250         for(i=0;i<NR_FILE;i++)
 251                 file_table[i].f_count=0;
 252         if (MAJOR(ROOT_DEV) == 2) {
 253                 printk("Insert root floppy and press ENTER");
 254                 wait_for_keypress();
 255         }
 256         for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) {
 257                 p->s_dev = 0;
 258                 p->s_lock = 0;
 259                 p->s_wait = NULL;
 260         }
 261         if (!(p=read_super(ROOT_DEV)))
 262                 panic("Unable to mount root");
 263         if (!(mi=iget(ROOT_DEV,ROOT_INO)))
 264                 panic("Unable to read root i-node");
 265         mi->i_count += 3 ;      /* NOTE! it is logically used 4 times, not 1 */
 266         p->s_isup = p->s_imount = mi;
 267         current->pwd = mi;
 268         current->root = mi;
 269         free=0;
 270         i=p->s_nzones;
 271         while (-- i >= 0)
 272                 if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
 273                         free++;
 274         printk("%d/%d free blocks\n\r",free,p->s_nzones);
 275         free=0;
 276         i=p->s_ninodes+1;
 277         while (-- i >= 0)
 278                 if (!set_bit(i&8191,p->s_imap[i>>13]->b_data))
 279                         free++;
 280         printk("%d/%d free inodes\n\r",free,p->s_ninodes);
 281 }

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