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. get_unnamed_dev
  8. put_unnamed_dev
  9. do_umount
  10. sys_umount
  11. do_mount
  12. do_remount
  13. sys_mount
  14. 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/kernel.h>
  13 #include <linux/stat.h>
  14 #include <linux/errno.h>
  15 #include <linux/string.h>
  16 #include <linux/locks.h>
  17 
  18 #include <asm/system.h>
  19 #include <asm/segment.h>
  20  
  21 /*
  22  * The definition of file_systems that used to be here is now in
  23  * filesystems.c.  Now super.c contains no fs specific code.  -- jrs
  24  */
  25 
  26 extern struct file_system_type file_systems[];
  27 extern struct file_operations * blkdev_fops[];
  28 
  29 extern void wait_for_keypress(void);
  30 extern void fcntl_init_locks(void);
  31 
  32 struct super_block super_block[NR_SUPER];
  33 
  34 /* this is initialized in init/main.c */
  35 dev_t ROOT_DEV = 0;
  36 
  37 struct file_system_type *get_fs_type(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39         int a;
  40         
  41         if (!name)
  42                 return &file_systems[0];
  43         for(a = 0 ; file_systems[a].read_super ; a++)
  44                 if (!strcmp(name,file_systems[a].name))
  45                         return(&file_systems[a]);
  46         return NULL;
  47 }
  48 
  49 void __wait_on_super(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51         struct wait_queue wait = { current, NULL };
  52 
  53         add_wait_queue(&sb->s_wait, &wait);
  54 repeat:
  55         current->state = TASK_UNINTERRUPTIBLE;
  56         if (sb->s_lock) {
  57                 schedule();
  58                 goto repeat;
  59         }
  60         remove_wait_queue(&sb->s_wait, &wait);
  61         current->state = TASK_RUNNING;
  62 }
  63 
  64 void sync_supers(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66         struct super_block * sb;
  67 
  68         for (sb = super_block + 0 ; sb < super_block + NR_SUPER ; sb++) {
  69                 if (!sb->s_dev)
  70                         continue;
  71                 if (dev && sb->s_dev != dev)
  72                         continue;
  73                 wait_on_super(sb);
  74                 if (!sb->s_dev || !sb->s_dirt)
  75                         continue;
  76                 if (dev && (dev != sb->s_dev))
  77                         continue;
  78                 if (sb->s_op && sb->s_op->write_super)
  79                         sb->s_op->write_super(sb);
  80         }
  81 }
  82 
  83 static struct super_block * get_super(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85         struct super_block * s;
  86 
  87         if (!dev)
  88                 return NULL;
  89         s = 0+super_block;
  90         while (s < NR_SUPER+super_block)
  91                 if (s->s_dev == dev) {
  92                         wait_on_super(s);
  93                         if (s->s_dev == dev)
  94                                 return s;
  95                         s = 0+super_block;
  96                 } else
  97                         s++;
  98         return NULL;
  99 }
 100 
 101 void put_super(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103         struct super_block * sb;
 104 
 105         if (dev == ROOT_DEV) {
 106                 printk("root diskette changed: prepare for armageddon\n\r");
 107                 return;
 108         }
 109         if (!(sb = get_super(dev)))
 110                 return;
 111         if (sb->s_covered) {
 112                 printk("Mounted disk changed - tssk, tssk\n\r");
 113                 return;
 114         }
 115         if (sb->s_op && sb->s_op->put_super)
 116                 sb->s_op->put_super(sb);
 117 }
 118 
 119 static struct super_block * read_super(dev_t dev,char *name,int flags,void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121         struct super_block * s;
 122         struct file_system_type *type;
 123 
 124         if (!dev)
 125                 return NULL;
 126         check_disk_change(dev);
 127         s = get_super(dev);
 128         if (s)
 129                 return s;
 130         if (!(type = get_fs_type(name))) {
 131                 printk("get fs type failed %s\n",name);
 132                 return NULL;
 133         }
 134         for (s = 0+super_block ;; s++) {
 135                 if (s >= NR_SUPER+super_block)
 136                         return NULL;
 137                 if (!s->s_dev)
 138                         break;
 139         }
 140         s->s_dev = dev;
 141         s->s_flags = flags;
 142         if (!type->read_super(s,data)) {
 143                 s->s_dev = 0;
 144                 return NULL;
 145         }
 146         s->s_dev = dev;
 147         s->s_covered = NULL;
 148         s->s_rd_only = 0;
 149         s->s_dirt = 0;
 150         return s;
 151 }
 152 
 153 /*
 154  * Unnamed block devices are dummy devices used by virtual
 155  * filesystems which don't use real block-devices.  -- jrs
 156  */
 157 
 158 static char unnamed_dev_in_use[256];
 159 
 160 static dev_t get_unnamed_dev(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 161 {
 162         static int first_use = 0;
 163         int i;
 164 
 165         if (first_use == 0) {
 166                 first_use = 1;
 167                 memset(unnamed_dev_in_use, 0, sizeof(unnamed_dev_in_use));
 168                 unnamed_dev_in_use[0] = 1; /* minor 0 (nodev) is special */
 169         }
 170         for (i = 0; i < 256; i++) {
 171                 if (!unnamed_dev_in_use[i]) {
 172                         unnamed_dev_in_use[i] = 1;
 173                         return (UNNAMED_MAJOR << 8) | i;
 174                 }
 175         }
 176         return 0;
 177 }
 178 
 179 static void put_unnamed_dev(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 180 {
 181         if (!dev)
 182                 return;
 183         if (!unnamed_dev_in_use[dev]) {
 184                 printk("put_unnamed_dev: trying to free unused device\n");
 185                 return;
 186         }
 187         unnamed_dev_in_use[dev] = 0;
 188 }
 189 
 190 static int do_umount(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192         struct super_block * sb;
 193 
 194         if (dev==ROOT_DEV)
 195                 return -EBUSY;
 196         if (!(sb=get_super(dev)) || !(sb->s_covered))
 197                 return -ENOENT;
 198         if (!sb->s_covered->i_mount)
 199                 printk("Mounted inode has i_mount=0\n");
 200         if (!fs_may_umount(dev, sb->s_mounted))
 201                 return -EBUSY;
 202         sb->s_covered->i_mount=0;
 203         iput(sb->s_covered);
 204         sb->s_covered = NULL;
 205         iput(sb->s_mounted);
 206         sb->s_mounted = NULL;
 207         if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
 208                 sb->s_op->write_super(sb);
 209         put_super(dev);
 210         return 0;
 211 }
 212 
 213 /*
 214  * Now umount can handle mount points as well as block devices.
 215  * This is important for filesystems which use unnamed block devices.
 216  *
 217  * There is a little kludge here with the dummy_inode.  The current
 218  * vfs release functions only use the r_dev field in the inode so
 219  * we give them the info they need without using a real inode.
 220  * If any other fields are ever needed by any block device release
 221  * functions, they should be faked here.  -- jrs
 222  */
 223 
 224 int sys_umount(char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
 225 {
 226         struct inode * inode;
 227         dev_t dev;
 228         int retval;
 229         struct inode dummy_inode;
 230         struct file_operations * fops;
 231 
 232         if (!suser())
 233                 return -EPERM;
 234         retval = namei(name,&inode);
 235         if (retval)
 236                 return retval;
 237         if (S_ISBLK(inode->i_mode)) {
 238                 dev = inode->i_rdev;
 239                 if (IS_NODEV(inode)) {
 240                         iput(inode);
 241                         return -EACCES;
 242                 }
 243         } else if (S_ISDIR(inode->i_mode)) {
 244                 if (!inode || !inode->i_sb || inode != inode->i_sb->s_mounted) {
 245                         iput(inode);
 246                         return -EINVAL;
 247                 }
 248                 dev = inode->i_sb->s_dev;
 249                 iput(inode);
 250                 memset(&dummy_inode, 0, sizeof(dummy_inode));
 251                 dummy_inode.i_rdev = dev;
 252                 inode = &dummy_inode;
 253         } else {
 254                 iput(inode);
 255                 return -EINVAL;
 256         }
 257         if (MAJOR(dev) >= MAX_BLKDEV) {
 258                 iput(inode);
 259                 return -ENXIO;
 260         }
 261         if (!(retval = do_umount(dev))) {
 262                 fops = blkdev_fops[MAJOR(dev)];
 263                 if (fops && fops->release)
 264                         fops->release(inode,NULL);
 265                 if (MAJOR(dev) == UNNAMED_MAJOR)
 266                         put_unnamed_dev(dev);
 267         }
 268         if (inode != &dummy_inode)
 269                 iput(inode);
 270         if (retval)
 271                 return retval;
 272         sync_dev(dev);
 273         return 0;
 274 }
 275 
 276 /*
 277  * do_mount() does the actual mounting after sys_mount has done the ugly
 278  * parameter parsing. When enough time has gone by, and everything uses the
 279  * new mount() parameters, sys_mount() can then be cleaned up.
 280  *
 281  * We cannot mount a filesystem if it has active, used, or dirty inodes.
 282  * We also have to flush all inode-data for this device, as the new mount
 283  * might need new info.
 284  */
 285 static int do_mount(dev_t dev, const char * dir, char * type, int flags, void * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 286 {
 287         struct inode * dir_i;
 288         struct super_block * sb;
 289         int error;
 290 
 291         error = namei(dir,&dir_i);
 292         if (error)
 293                 return error;
 294         if (dir_i->i_count != 1 || dir_i->i_mount) {
 295                 iput(dir_i);
 296                 return -EBUSY;
 297         }
 298         if (!S_ISDIR(dir_i->i_mode)) {
 299                 iput(dir_i);
 300                 return -EPERM;
 301         }
 302         if (!fs_may_mount(dev)) {
 303                 iput(dir_i);
 304                 return -EBUSY;
 305         }
 306         sb = read_super(dev,type,flags,data);
 307         if (!sb || sb->s_covered) {
 308                 iput(dir_i);
 309                 return -EBUSY;
 310         }
 311         sb->s_covered = dir_i;
 312         dir_i->i_mount = 1;
 313         return 0;               /* we don't iput(dir_i) - see umount */
 314 }
 315 
 316 
 317 /*
 318  * Alters the mount flags of a mounted file system. Only the mount point
 319  * is used as a reference - file system type and the device are ignored.
 320  * FS-specific mount options can't be altered by remounting.
 321  */
 322 
 323 static int do_remount(const char *dir,int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 324 {
 325         struct inode *dir_i;
 326         int retval;
 327 
 328         retval = namei(dir,&dir_i);
 329         if (retval)
 330                 return retval;
 331         if (dir_i != dir_i->i_sb->s_mounted) {
 332                 iput(dir_i);
 333                 return -EINVAL;
 334         }
 335         dir_i->i_sb->s_flags = (dir_i->i_sb->s_flags & ~MS_RMT_MASK) |
 336                 (flags & MS_RMT_MASK);
 337         iput(dir_i);
 338         return 0;
 339 }
 340 
 341 
 342 /*
 343  * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to
 344  * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
 345  *
 346  * data is a (void *) that can point to any structure up to 4095 bytes, which
 347  * can contain arbitrary fs-dependent information (or be NULL).
 348  *
 349  * NOTE! As old versions of mount() didn't use this setup, the flags has to have
 350  * a special 16-bit magic number in the hight word: 0xC0ED. If this magic word
 351  * isn't present, the flags and data info isn't used, as the syscall assumes we
 352  * are talking to an older version that didn't understand them.
 353  */
 354 int sys_mount(char * dev_name, char * dir_name, char * type,
     /* [previous][next][first][last][top][bottom][index][help] */
 355         unsigned long new_flags, void * data)
 356 {
 357         struct file_system_type * fstype;
 358         struct inode * inode;
 359         struct file_operations * fops;
 360         dev_t dev;
 361         int retval;
 362         char tmp[100], * t;
 363         int i;
 364         unsigned long flags = 0;
 365         unsigned long page = 0;
 366 
 367         if (!suser())
 368                 return -EPERM;
 369         if ((new_flags & (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL |
 370             MS_REMOUNT))
 371                 return do_remount(dir_name,new_flags & ~MS_MGC_MSK &
 372                     ~MS_REMOUNT);
 373         if (type) {
 374                 for (i = 0 ; i < 100 ; i++)
 375                         if (!(tmp[i] = get_fs_byte(type++)))
 376                                 break;
 377                 t = tmp;
 378         } else
 379                 t = NULL;
 380         if (!(fstype = get_fs_type(t)))
 381                 return -ENODEV;
 382         t = fstype->name;
 383         if (fstype->requires_dev) {
 384                 retval = namei(dev_name,&inode);
 385                 if (retval)
 386                         return retval;
 387                 if (!S_ISBLK(inode->i_mode)) {
 388                         iput(inode);
 389                         return -ENOTBLK;
 390                 }
 391                 if (IS_NODEV(inode)) {
 392                         iput(inode);
 393                         return -EACCES;
 394                 }
 395                 dev = inode->i_rdev;
 396                 if (MAJOR(dev) >= MAX_BLKDEV) {
 397                         iput(inode);
 398                         return -ENXIO;
 399                 }
 400         }
 401         else {
 402                 if (!(dev = get_unnamed_dev()))
 403                         return -EMFILE;
 404                 inode = NULL;
 405         }
 406         fops = blkdev_fops[MAJOR(dev)];
 407         if (fops && fops->open) {
 408                 retval = fops->open(inode,NULL);
 409                 if (retval) {
 410                         iput(inode);
 411                         return retval;
 412                 }
 413         }
 414         if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) {
 415                 flags = new_flags & ~MS_MGC_MSK;
 416                 if (data) {
 417                         if ((unsigned long) data >= TASK_SIZE) {
 418                                 iput(inode);
 419                                 return -EFAULT;
 420                         }
 421                         page = get_free_page(GFP_KERNEL);
 422                         i = TASK_SIZE - (unsigned long) data;
 423                         if (i < 0 || i > 4095)
 424                                 i = 4095;
 425                         memcpy_fromfs((void *) page,data,i);
 426                 }
 427         }
 428         retval = do_mount(dev,dir_name,t,flags,(void *) page);
 429         free_page(page);
 430         if (retval && fops && fops->release)
 431                 fops->release(inode,NULL);
 432         iput(inode);
 433         return retval;
 434 }
 435 
 436 void mount_root(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 437 {
 438         struct file_system_type * fs_type;
 439         struct super_block * sb;
 440         struct inode * inode;
 441 
 442         memset(file_table, 0, sizeof(file_table));
 443         memset(super_block, 0, sizeof(super_block));
 444         fcntl_init_locks();
 445         if (MAJOR(ROOT_DEV) == 2) {
 446                 printk("Insert root floppy and press ENTER");
 447                 wait_for_keypress();
 448         }
 449         for (fs_type = file_systems; fs_type->read_super; fs_type++) {
 450                 if (!fs_type->requires_dev)
 451                         continue;
 452                 sb = read_super(ROOT_DEV,fs_type->name,0,NULL);
 453                 if (sb) {
 454                         inode = sb->s_mounted;
 455                         inode->i_count += 3 ;   /* NOTE! it is logically used 4 times, not 1 */
 456                         sb->s_covered = inode;
 457                         sb->s_flags = 0;
 458                         current->pwd = inode;
 459                         current->root = inode;
 460                         return;
 461                 }
 462         }
 463         panic("Unable to mount root");
 464 }

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