root/fs/super.c

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

DEFINITIONS

This source file includes following definitions.
  1. lookup_vfsmnt
  2. add_vfsmnt
  3. remove_vfsmnt
  4. register_filesystem
  5. unregister_filesystem
  6. fs_index
  7. fs_name
  8. fs_maxindex
  9. sys_sysfs
  10. get_filesystem_info
  11. get_filesystem_list
  12. get_fs_type
  13. __wait_on_super
  14. sync_supers
  15. get_super
  16. put_super
  17. sys_ustat
  18. read_super
  19. get_unnamed_dev
  20. put_unnamed_dev
  21. do_umount
  22. sys_umount
  23. do_mount
  24. do_remount_sb
  25. do_remount
  26. copy_mount_options
  27. sys_mount
  28. mount_root

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

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