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

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