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

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