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

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