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

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