root/fs/super.c

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

DEFINITIONS

This source file includes following definitions.
  1. register_filesystem
  2. unregister_filesystem
  3. fs_index
  4. fs_name
  5. fs_maxindex
  6. sys_sysfs
  7. get_filesystem_list
  8. get_fs_type
  9. __wait_on_super
  10. sync_supers
  11. get_super
  12. put_super
  13. sys_ustat
  14. read_super
  15. get_unnamed_dev
  16. put_unnamed_dev
  17. do_umount
  18. sys_umount
  19. do_mount
  20. do_remount_sb
  21. do_remount
  22. copy_mount_options
  23. sys_mount
  24. 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 <stdarg.h>
  11 
  12 #include <linux/config.h>
  13 #include <linux/sched.h>
  14 #include <linux/kernel.h>
  15 #include <linux/major.h>
  16 #include <linux/stat.h>
  17 #include <linux/errno.h>
  18 #include <linux/string.h>
  19 #include <linux/locks.h>
  20 #include <linux/mm.h>
  21 
  22 #include <asm/system.h>
  23 #include <asm/segment.h>
  24 #include <asm/bitops.h>
  25  
  26 extern struct file_operations * get_blkfops(unsigned int);
  27 extern struct file_operations * get_chrfops(unsigned int);
  28 
  29 extern void wait_for_keypress(void);
  30 
  31 extern int root_mountflags;
  32 
  33 struct super_block super_blocks[NR_SUPER];
  34 
  35 static int do_remount_sb(struct super_block *sb, int flags, char * data);
  36 
  37 /* this is initialized in init/main.c */
  38 dev_t ROOT_DEV = 0;
  39 
  40 static struct file_system_type * file_systems = NULL;
  41 
  42 int register_filesystem(struct file_system_type * fs)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44         struct file_system_type ** tmp;
  45 
  46         if (!fs)
  47                 return -EINVAL;
  48         if (fs->next)
  49                 return -EBUSY;
  50         tmp = &file_systems;
  51         while (*tmp) {
  52                 if (strcmp((*tmp)->name, fs->name) == 0)
  53                         return -EBUSY;
  54                 tmp = &(*tmp)->next;
  55         }
  56         *tmp = fs;
  57         return 0;
  58 }
  59 
  60 int unregister_filesystem(struct file_system_type * fs)
     /* [previous][next][first][last][top][bottom][index][help] */
  61 {
  62         struct file_system_type ** tmp;
  63 
  64         tmp = &file_systems;
  65         while (*tmp) {
  66                 if (fs == *tmp) {
  67                         *tmp = fs->next;
  68                         fs->next = NULL;
  69                         return 0;
  70                 }
  71                 tmp = &(*tmp)->next;
  72         }
  73         return -EINVAL;
  74 }
  75 
  76 static int fs_index(const char * __name)
     /* [previous][next][first][last][top][bottom][index][help] */
  77 {
  78         struct file_system_type * tmp;
  79         char * name;
  80         int err, index;
  81 
  82         err = getname(__name, &name);
  83         if (err)
  84                 return err;
  85         index = 0;
  86         for (tmp = file_systems ; tmp ; tmp = tmp->next) {
  87                 if (strcmp(tmp->name, name) == 0) {
  88                         putname(name);
  89                         return index;
  90                 }
  91                 index++;
  92         }
  93         putname(name);
  94         return -EINVAL;
  95 }
  96 
  97 static int fs_name(unsigned int index, char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99         struct file_system_type * tmp;
 100         int err, len;
 101 
 102         tmp = file_systems;
 103         while (tmp && index > 0) {
 104                 tmp = tmp->next;
 105                 index--;
 106         }
 107         if (!tmp)
 108                 return -EINVAL;
 109         len = strlen(tmp->name) + 1;
 110         err = verify_area(VERIFY_WRITE, buf, len);
 111         if (err)
 112                 return err;
 113         memcpy_tofs(buf, tmp->name, len);
 114         return 0;
 115 }
 116 
 117 static int fs_maxindex(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119         struct file_system_type * tmp;
 120         int index;
 121 
 122         index = 0;
 123         for (tmp = file_systems ; tmp ; tmp = tmp->next)
 124                 index++;
 125         return index;
 126 }
 127 
 128 /*
 129  * Whee.. Weird sysv syscall. 
 130  */
 131 asmlinkage int sys_sysfs(int option, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
 132 {
 133         va_list args;
 134         int retval = -EINVAL;
 135         unsigned int index;
 136 
 137         va_start(args, option);
 138         switch (option) {
 139                 case 1:
 140                         retval = fs_index(va_arg(args, const char *));
 141                         break;
 142 
 143                 case 2:
 144                         index = va_arg(args, unsigned int);
 145                         retval = fs_name(index, va_arg(args, char *));
 146                         break;
 147 
 148                 case 3:
 149                         retval = fs_maxindex();
 150                         break;
 151         }
 152         va_end(args);
 153         return retval;
 154 }
 155 
 156 int get_filesystem_list(char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158         int len = 0;
 159         struct file_system_type * tmp;
 160 
 161         tmp = file_systems;
 162         while (tmp && len < PAGE_SIZE - 80) {
 163                 len += sprintf(buf+len, "%s\t%s\n",
 164                         tmp->requires_dev ? "" : "nodev",
 165                         tmp->name);
 166                 tmp = tmp->next;
 167         }
 168         return len;
 169 }
 170 
 171 struct file_system_type *get_fs_type(const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         struct file_system_type * fs = file_systems;
 174         
 175         if (!name)
 176                 return fs;
 177         while (fs) {
 178                 if (!strcmp(name,fs->name))
 179                         break;
 180                 fs = fs->next;
 181         }
 182         return fs;
 183 }
 184 
 185 void __wait_on_super(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187         struct wait_queue wait = { current, NULL };
 188 
 189         add_wait_queue(&sb->s_wait, &wait);
 190 repeat:
 191         current->state = TASK_UNINTERRUPTIBLE;
 192         if (sb->s_lock) {
 193                 schedule();
 194                 goto repeat;
 195         }
 196         remove_wait_queue(&sb->s_wait, &wait);
 197         current->state = TASK_RUNNING;
 198 }
 199 
 200 void sync_supers(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202         struct super_block * sb;
 203 
 204         for (sb = super_blocks + 0 ; sb < super_blocks + NR_SUPER ; sb++) {
 205                 if (!sb->s_dev)
 206                         continue;
 207                 if (dev && sb->s_dev != dev)
 208                         continue;
 209                 wait_on_super(sb);
 210                 if (!sb->s_dev || !sb->s_dirt)
 211                         continue;
 212                 if (dev && (dev != sb->s_dev))
 213                         continue;
 214                 if (sb->s_op && sb->s_op->write_super)
 215                         sb->s_op->write_super(sb);
 216         }
 217 }
 218 
 219 static struct super_block * get_super(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 220 {
 221         struct super_block * s;
 222 
 223         if (!dev)
 224                 return NULL;
 225         s = 0+super_blocks;
 226         while (s < NR_SUPER+super_blocks)
 227                 if (s->s_dev == dev) {
 228                         wait_on_super(s);
 229                         if (s->s_dev == dev)
 230                                 return s;
 231                         s = 0+super_blocks;
 232                 } else
 233                         s++;
 234         return NULL;
 235 }
 236 
 237 void put_super(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 238 {
 239         struct super_block * sb;
 240 
 241         if (dev == ROOT_DEV) {
 242                 printk("VFS: Root device %d/%d: prepare for armageddon\n",
 243                                                         MAJOR(dev), MINOR(dev));
 244                 return;
 245         }
 246         if (!(sb = get_super(dev)))
 247                 return;
 248         if (sb->s_covered) {
 249                 printk("VFS: Mounted device %d/%d - tssk, tssk\n",
 250                                                 MAJOR(dev), MINOR(dev));
 251                 return;
 252         }
 253         if (sb->s_op && sb->s_op->put_super)
 254                 sb->s_op->put_super(sb);
 255 }
 256 
 257 asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {
 259         struct super_block *s;
 260         struct ustat tmp;
 261         struct statfs sbuf;
 262         unsigned long old_fs;
 263         int error;
 264 
 265         s = get_super(dev);
 266         if (s == NULL)
 267                 return -EINVAL;
 268 
 269         if (!(s->s_op->statfs))
 270                 return -ENOSYS;
 271 
 272         error = verify_area(VERIFY_WRITE,ubuf,sizeof(struct ustat));
 273         if (error)
 274                 return error;
 275 
 276         old_fs = get_fs();
 277         set_fs(get_ds());
 278         s->s_op->statfs(s,&sbuf,sizeof(struct statfs));
 279         set_fs(old_fs);
 280 
 281         memset(&tmp,0,sizeof(struct ustat));
 282         tmp.f_tfree = sbuf.f_bfree;
 283         tmp.f_tinode = sbuf.f_ffree;
 284 
 285         memcpy_tofs(ubuf,&tmp,sizeof(struct ustat));
 286         return 0;
 287 }
 288 
 289 static struct super_block * read_super(dev_t dev,const char *name,int flags,
     /* [previous][next][first][last][top][bottom][index][help] */
 290                                        void *data, int silent)
 291 {
 292         struct super_block * s;
 293         struct file_system_type *type;
 294 
 295         if (!dev)
 296                 return NULL;
 297         check_disk_change(dev);
 298         s = get_super(dev);
 299         if (s)
 300                 return s;
 301         if (!(type = get_fs_type(name))) {
 302                 printk("VFS: on device %d/%d: get_fs_type(%s) failed\n",
 303                                                 MAJOR(dev), MINOR(dev), name);
 304                 return NULL;
 305         }
 306         for (s = 0+super_blocks ;; s++) {
 307                 if (s >= NR_SUPER+super_blocks)
 308                         return NULL;
 309                 if (!s->s_dev)
 310                         break;
 311         }
 312         s->s_dev = dev;
 313         s->s_flags = flags;
 314         if (!type->read_super(s,data, silent)) {
 315                 s->s_dev = 0;
 316                 return NULL;
 317         }
 318         s->s_dev = dev;
 319         s->s_covered = NULL;
 320         s->s_rd_only = 0;
 321         s->s_dirt = 0;
 322         s->s_type = type;
 323         return s;
 324 }
 325 
 326 /*
 327  * Unnamed block devices are dummy devices used by virtual
 328  * filesystems which don't use real block-devices.  -- jrs
 329  */
 330 
 331 static char unnamed_dev_in_use[256/8] = { 0, };
 332 
 333 static dev_t get_unnamed_dev(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 334 {
 335         int i;
 336 
 337         for (i = 1; i < 256; i++) {
 338                 if (!set_bit(i,unnamed_dev_in_use))
 339                         return (UNNAMED_MAJOR << 8) | i;
 340         }
 341         return 0;
 342 }
 343 
 344 static void put_unnamed_dev(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 345 {
 346         if (!dev)
 347                 return;
 348         if (MAJOR(dev) == UNNAMED_MAJOR &&
 349             clear_bit(MINOR(dev), unnamed_dev_in_use))
 350                 return;
 351         printk("VFS: put_unnamed_dev: freeing unused device %d/%d\n",
 352                         MAJOR(dev), MINOR(dev));
 353 }
 354 
 355 static int do_umount(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 356 {
 357         struct super_block * sb;
 358         int retval;
 359         
 360         if (dev==ROOT_DEV) {
 361                 /* Special case for "unmounting" root.  We just try to remount
 362                    it readonly, and sync() the device. */
 363                 if (!(sb=get_super(dev)))
 364                         return -ENOENT;
 365                 if (!(sb->s_flags & MS_RDONLY)) {
 366                         fsync_dev(dev);
 367                         retval = do_remount_sb(sb, MS_RDONLY, 0);
 368                         if (retval)
 369                                 return retval;
 370                 }
 371                 return 0;
 372         }
 373         if (!(sb=get_super(dev)) || !(sb->s_covered))
 374                 return -ENOENT;
 375         if (!sb->s_covered->i_mount)
 376                 printk("VFS: umount(%d/%d): mounted inode has i_mount=NULL\n",
 377                                                         MAJOR(dev), MINOR(dev));
 378         if (!fs_may_umount(dev, sb->s_mounted))
 379                 return -EBUSY;
 380         sb->s_covered->i_mount = NULL;
 381         iput(sb->s_covered);
 382         sb->s_covered = NULL;
 383         iput(sb->s_mounted);
 384         sb->s_mounted = NULL;
 385         if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
 386                 sb->s_op->write_super(sb);
 387         put_super(dev);
 388         return 0;
 389 }
 390 
 391 /*
 392  * Now umount can handle mount points as well as block devices.
 393  * This is important for filesystems which use unnamed block devices.
 394  *
 395  * There is a little kludge here with the dummy_inode.  The current
 396  * vfs release functions only use the r_dev field in the inode so
 397  * we give them the info they need without using a real inode.
 398  * If any other fields are ever needed by any block device release
 399  * functions, they should be faked here.  -- jrs
 400  */
 401 
 402 asmlinkage int sys_umount(char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
 403 {
 404         struct inode * inode;
 405         dev_t dev;
 406         int retval;
 407         struct inode dummy_inode;
 408         struct file_operations * fops;
 409 
 410         if (!suser())
 411                 return -EPERM;
 412         retval = namei(name,&inode);
 413         if (retval) {
 414                 retval = lnamei(name,&inode);
 415                 if (retval)
 416                         return retval;
 417         }
 418         if (S_ISBLK(inode->i_mode)) {
 419                 dev = inode->i_rdev;
 420                 if (IS_NODEV(inode)) {
 421                         iput(inode);
 422                         return -EACCES;
 423                 }
 424         } else {
 425                 if (!inode->i_sb || inode != inode->i_sb->s_mounted) {
 426                         iput(inode);
 427                         return -EINVAL;
 428                 }
 429                 dev = inode->i_sb->s_dev;
 430                 iput(inode);
 431                 memset(&dummy_inode, 0, sizeof(dummy_inode));
 432                 dummy_inode.i_rdev = dev;
 433                 inode = &dummy_inode;
 434         }
 435         if (MAJOR(dev) >= MAX_BLKDEV) {
 436                 iput(inode);
 437                 return -ENXIO;
 438         }
 439         if (!(retval = do_umount(dev)) && dev != ROOT_DEV) {
 440                 fops = get_blkfops(MAJOR(dev));
 441                 if (fops && fops->release)
 442                         fops->release(inode,NULL);
 443                 if (MAJOR(dev) == UNNAMED_MAJOR)
 444                         put_unnamed_dev(dev);
 445         }
 446         if (inode != &dummy_inode)
 447                 iput(inode);
 448         if (retval)
 449                 return retval;
 450         fsync_dev(dev);
 451         return 0;
 452 }
 453 
 454 /*
 455  * do_mount() does the actual mounting after sys_mount has done the ugly
 456  * parameter parsing. When enough time has gone by, and everything uses the
 457  * new mount() parameters, sys_mount() can then be cleaned up.
 458  *
 459  * We cannot mount a filesystem if it has active, used, or dirty inodes.
 460  * We also have to flush all inode-data for this device, as the new mount
 461  * might need new info.
 462  */
 463 static int do_mount(dev_t dev, const char * dir, const char * type, int flags, void * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 464 {
 465         struct inode * dir_i;
 466         struct super_block * sb;
 467         int error;
 468 
 469         error = namei(dir,&dir_i);
 470         if (error)
 471                 return error;
 472         if (dir_i->i_count != 1 || dir_i->i_mount) {
 473                 iput(dir_i);
 474                 return -EBUSY;
 475         }
 476         if (!S_ISDIR(dir_i->i_mode)) {
 477                 iput(dir_i);
 478                 return -ENOTDIR;
 479         }
 480         if (!fs_may_mount(dev)) {
 481                 iput(dir_i);
 482                 return -EBUSY;
 483         }
 484         sb = read_super(dev,type,flags,data,0);
 485         if (!sb) {
 486                 iput(dir_i);
 487                 return -EINVAL;
 488         }
 489         if (sb->s_covered) {
 490                 iput(dir_i);
 491                 return -EBUSY;
 492         }
 493         sb->s_covered = dir_i;
 494         dir_i->i_mount = sb->s_mounted;
 495         return 0;               /* we don't iput(dir_i) - see umount */
 496 }
 497 
 498 
 499 /*
 500  * Alters the mount flags of a mounted file system. Only the mount point
 501  * is used as a reference - file system type and the device are ignored.
 502  * FS-specific mount options can't be altered by remounting.
 503  */
 504 
 505 static int do_remount_sb(struct super_block *sb, int flags, char *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 506 {
 507         int retval;
 508         
 509         if (!(flags & MS_RDONLY ) && sb->s_dev && is_read_only(sb->s_dev))
 510                 return -EACCES;
 511                 /*flags |= MS_RDONLY;*/
 512         /* If we are remounting RDONLY, make sure there are no rw files open */
 513         if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
 514                 if (!fs_may_remount_ro(sb->s_dev))
 515                         return -EBUSY;
 516         if (sb->s_op && sb->s_op->remount_fs) {
 517                 retval = sb->s_op->remount_fs(sb, &flags, data);
 518                 if (retval)
 519                         return retval;
 520         }
 521         sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) |
 522                 (flags & MS_RMT_MASK);
 523         return 0;
 524 }
 525 
 526 static int do_remount(const char *dir,int flags,char *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 527 {
 528         struct inode *dir_i;
 529         int retval;
 530 
 531         retval = namei(dir,&dir_i);
 532         if (retval)
 533                 return retval;
 534         if (dir_i != dir_i->i_sb->s_mounted) {
 535                 iput(dir_i);
 536                 return -EINVAL;
 537         }
 538         retval = do_remount_sb(dir_i->i_sb, flags, data);
 539         iput(dir_i);
 540         return retval;
 541 }
 542 
 543 static int copy_mount_options (const void * data, unsigned long *where)
     /* [previous][next][first][last][top][bottom][index][help] */
 544 {
 545         int i;
 546         unsigned long page;
 547         struct vm_area_struct * vma;
 548 
 549         *where = 0;
 550         if (!data)
 551                 return 0;
 552 
 553         vma = find_vma(current, (unsigned long) data);
 554         if (!vma || (unsigned long) data < vma->vm_start)
 555                 return -EFAULT;
 556         i = vma->vm_end - (unsigned long) data;
 557         if (PAGE_SIZE <= (unsigned long) i)
 558                 i = PAGE_SIZE-1;
 559         if (!(page = __get_free_page(GFP_KERNEL))) {
 560                 return -ENOMEM;
 561         }
 562         memcpy_fromfs((void *) page,data,i);
 563         *where = page;
 564         return 0;
 565 }
 566 
 567 /*
 568  * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to
 569  * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
 570  *
 571  * data is a (void *) that can point to any structure up to
 572  * PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent
 573  * information (or be NULL).
 574  *
 575  * NOTE! As old versions of mount() didn't use this setup, the flags
 576  * has to have a special 16-bit magic number in the hight word:
 577  * 0xC0ED. If this magic word isn't present, the flags and data info
 578  * isn't used, as the syscall assumes we are talking to an older
 579  * version that didn't understand them.
 580  */
 581 asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
     /* [previous][next][first][last][top][bottom][index][help] */
 582         unsigned long new_flags, void * data)
 583 {
 584         struct file_system_type * fstype;
 585         struct inode * inode;
 586         struct file_operations * fops;
 587         dev_t dev;
 588         int retval;
 589         const char * t;
 590         unsigned long flags = 0;
 591         unsigned long page = 0;
 592 
 593         if (!suser())
 594                 return -EPERM;
 595         if ((new_flags &
 596              (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) {
 597                 retval = copy_mount_options (data, &page);
 598                 if (retval < 0)
 599                         return retval;
 600                 retval = do_remount(dir_name,
 601                                     new_flags & ~MS_MGC_MSK & ~MS_REMOUNT,
 602                                     (char *) page);
 603                 free_page(page);
 604                 return retval;
 605         }
 606         retval = copy_mount_options (type, &page);
 607         if (retval < 0)
 608                 return retval;
 609         fstype = get_fs_type((char *) page);
 610         free_page(page);
 611         if (!fstype)            
 612                 return -ENODEV;
 613         t = fstype->name;
 614         fops = NULL;
 615         if (fstype->requires_dev) {
 616                 retval = namei(dev_name,&inode);
 617                 if (retval)
 618                         return retval;
 619                 if (!S_ISBLK(inode->i_mode)) {
 620                         iput(inode);
 621                         return -ENOTBLK;
 622                 }
 623                 if (IS_NODEV(inode)) {
 624                         iput(inode);
 625                         return -EACCES;
 626                 }
 627                 dev = inode->i_rdev;
 628                 if (MAJOR(dev) >= MAX_BLKDEV) {
 629                         iput(inode);
 630                         return -ENXIO;
 631                 }
 632                 fops = get_blkfops(MAJOR(dev));
 633                 if (!fops) {
 634                         iput(inode);
 635                         return -ENOTBLK;
 636                 }
 637                 if (fops->open) {
 638                         struct file dummy;      /* allows read-write or read-only flag */
 639                         memset(&dummy, 0, sizeof(dummy));
 640                         dummy.f_inode = inode;
 641                         dummy.f_mode = (new_flags & MS_RDONLY) ? 1 : 3;
 642                         retval = fops->open(inode, &dummy);
 643                         if (retval) {
 644                                 iput(inode);
 645                                 return retval;
 646                         }
 647                 }
 648 
 649         } else {
 650                 if (!(dev = get_unnamed_dev()))
 651                         return -EMFILE;
 652                 inode = NULL;
 653         }
 654         page = 0;
 655         if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) {
 656                 flags = new_flags & ~MS_MGC_MSK;
 657                 retval = copy_mount_options(data, &page);
 658                 if (retval < 0) {
 659                         iput(inode);
 660                         return retval;
 661                 }
 662         }
 663         retval = do_mount(dev,dir_name,t,flags,(void *) page);
 664         free_page(page);
 665         if (retval && fops && fops->release)
 666                 fops->release(inode, NULL);
 667         iput(inode);
 668         return retval;
 669 }
 670 
 671 void mount_root(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 672 {
 673         struct file_system_type * fs_type;
 674         struct super_block * sb;
 675         struct inode * inode, d_inode;
 676         struct file filp;
 677         int retval;
 678 
 679         memset(super_blocks, 0, sizeof(super_blocks));
 680 #ifdef CONFIG_BLK_DEV_FD
 681         if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
 682                 printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
 683                 wait_for_keypress();
 684         }
 685 #endif
 686 
 687         memset(&filp, 0, sizeof(filp));
 688         memset(&d_inode, 0, sizeof(d_inode));
 689         d_inode.i_rdev = ROOT_DEV;
 690         filp.f_inode = &d_inode;
 691         if ( root_mountflags & MS_RDONLY)
 692                 filp.f_mode = 1; /* read only */
 693         else
 694                 filp.f_mode = 3; /* read write */
 695         retval = blkdev_open(&d_inode, &filp);
 696         if(retval == -EROFS){
 697                 root_mountflags |= MS_RDONLY;
 698                 filp.f_mode = 1;
 699                 retval = blkdev_open(&d_inode, &filp);
 700         }
 701 
 702         for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
 703                 if(retval)
 704                         break;
 705                 if (!fs_type->requires_dev)
 706                         continue;
 707                 sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
 708                 if (sb) {
 709                         inode = sb->s_mounted;
 710                         inode->i_count += 3 ;   /* NOTE! it is logically used 4 times, not 1 */
 711                         sb->s_covered = inode;
 712                         sb->s_flags = root_mountflags;
 713                         current->fs->pwd = inode;
 714                         current->fs->root = inode;
 715                         printk ("VFS: Mounted root (%s filesystem)%s.\n",
 716                                 fs_type->name,
 717                                 (sb->s_flags & MS_RDONLY) ? " readonly" : "");
 718                         return;
 719                 }
 720         }
 721         panic("VFS: Unable to mount root fs on %02x:%02x",
 722                 MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
 723 }

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