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

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