root/fs/super.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_fs_type
  2. __wait_on_super
  3. sync_supers
  4. get_super
  5. put_super
  6. read_super
  7. get_unnamed_dev
  8. put_unnamed_dev
  9. do_umount
  10. sys_umount
  11. do_mount
  12. do_remount_sb
  13. do_remount
  14. copy_mount_options
  15. sys_mount
  16. mount_root

   1 /*
   2  *  linux/fs/super.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  * super.c contains code to handle the super-block tables.
   9  */
  10 #include <linux/config.h>
  11 #include <linux/sched.h>
  12 #include <linux/kernel.h>
  13 #include <linux/major.h>
  14 #include <linux/stat.h>
  15 #include <linux/errno.h>
  16 #include <linux/string.h>
  17 #include <linux/locks.h>
  18 
  19 #include <asm/system.h>
  20 #include <asm/segment.h>
  21 
  22  
  23 /*
  24  * The definition of file_systems that used to be here is now in
  25  * filesystems.c.  Now super.c contains no fs specific code.  -- jrs
  26  */
  27 
  28 extern struct file_system_type file_systems[];
  29 extern struct file_operations * get_blkfops(unsigned int);
  30 extern struct file_operations * get_chrfops(unsigned int);
  31 
  32 extern void wait_for_keypress(void);
  33 extern void fcntl_init_locks(void);
  34 
  35 extern int root_mountflags;
  36 
  37 struct super_block super_blocks[NR_SUPER];
  38 
  39 static int do_remount_sb(struct super_block *sb, int flags, char * data);
  40 
  41 /* this is initialized in init/main.c */
  42 dev_t ROOT_DEV = 0;
  43 
  44 struct file_system_type *get_fs_type(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46         int a;
  47         
  48         if (!name)
  49                 return &file_systems[0];
  50         for(a = 0 ; file_systems[a].read_super ; a++)
  51                 if (!strcmp(name,file_systems[a].name))
  52                         return(&file_systems[a]);
  53         return NULL;
  54 }
  55 
  56 void __wait_on_super(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  57 {
  58         struct wait_queue wait = { current, NULL };
  59 
  60         add_wait_queue(&sb->s_wait, &wait);
  61 repeat:
  62         current->state = TASK_UNINTERRUPTIBLE;
  63         if (sb->s_lock) {
  64                 schedule();
  65                 goto repeat;
  66         }
  67         remove_wait_queue(&sb->s_wait, &wait);
  68         current->state = TASK_RUNNING;
  69 }
  70 
  71 void sync_supers(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73         struct super_block * sb;
  74 
  75         for (sb = super_blocks + 0 ; sb < super_blocks + NR_SUPER ; sb++) {
  76                 if (!sb->s_dev)
  77                         continue;
  78                 if (dev && sb->s_dev != dev)
  79                         continue;
  80                 wait_on_super(sb);
  81                 if (!sb->s_dev || !sb->s_dirt)
  82                         continue;
  83                 if (dev && (dev != sb->s_dev))
  84                         continue;
  85                 if (sb->s_op && sb->s_op->write_super)
  86                         sb->s_op->write_super(sb);
  87         }
  88 }
  89 
  90 static struct super_block * get_super(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92         struct super_block * s;
  93 
  94         if (!dev)
  95                 return NULL;
  96         s = 0+super_blocks;
  97         while (s < NR_SUPER+super_blocks)
  98                 if (s->s_dev == dev) {
  99                         wait_on_super(s);
 100                         if (s->s_dev == dev)
 101                                 return s;
 102                         s = 0+super_blocks;
 103                 } else
 104                         s++;
 105         return NULL;
 106 }
 107 
 108 void put_super(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 109 {
 110         struct super_block * sb;
 111 
 112         if (dev == ROOT_DEV) {
 113                 printk("VFS: Root device %d/%d: prepare for armageddon\n",
 114                                                         MAJOR(dev), MINOR(dev));
 115                 return;
 116         }
 117         if (!(sb = get_super(dev)))
 118                 return;
 119         if (sb->s_covered) {
 120                 printk("VFS: Mounted device %d/%d - tssk, tssk\n",
 121                                                 MAJOR(dev), MINOR(dev));
 122                 return;
 123         }
 124         if (sb->s_op && sb->s_op->put_super)
 125                 sb->s_op->put_super(sb);
 126 }
 127 
 128 static struct super_block * read_super(dev_t dev,char *name,int flags,
     /* [previous][next][first][last][top][bottom][index][help] */
 129                                        void *data, int silent)
 130 {
 131         struct super_block * s;
 132         struct file_system_type *type;
 133 
 134         if (!dev)
 135                 return NULL;
 136         check_disk_change(dev);
 137         s = get_super(dev);
 138         if (s)
 139                 return s;
 140         if (!(type = get_fs_type(name))) {
 141                 printk("VFS: on device %d/%d: get_fs_type(%s) failed\n",
 142                                                 MAJOR(dev), MINOR(dev), name);
 143                 return NULL;
 144         }
 145         for (s = 0+super_blocks ;; s++) {
 146                 if (s >= NR_SUPER+super_blocks)
 147                         return NULL;
 148                 if (!s->s_dev)
 149                         break;
 150         }
 151         s->s_dev = dev;
 152         s->s_flags = flags;
 153         if (!type->read_super(s,data, silent)) {
 154                 s->s_dev = 0;
 155                 return NULL;
 156         }
 157         s->s_dev = dev;
 158         s->s_covered = NULL;
 159         s->s_rd_only = 0;
 160         s->s_dirt = 0;
 161         return s;
 162 }
 163 
 164 /*
 165  * Unnamed block devices are dummy devices used by virtual
 166  * filesystems which don't use real block-devices.  -- jrs
 167  */
 168 
 169 static char unnamed_dev_in_use[256];
 170 
 171 static dev_t get_unnamed_dev(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         static int first_use = 0;
 174         int i;
 175 
 176         if (first_use == 0) {
 177                 first_use = 1;
 178                 memset(unnamed_dev_in_use, 0, sizeof(unnamed_dev_in_use));
 179                 unnamed_dev_in_use[0] = 1; /* minor 0 (nodev) is special */
 180         }
 181         for (i = 0; i < sizeof unnamed_dev_in_use/sizeof unnamed_dev_in_use[0]; i++) {
 182                 if (!unnamed_dev_in_use[i]) {
 183                         unnamed_dev_in_use[i] = 1;
 184                         return (UNNAMED_MAJOR << 8) | i;
 185                 }
 186         }
 187         return 0;
 188 }
 189 
 190 static void put_unnamed_dev(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192         if (!dev)
 193                 return;
 194         if (!unnamed_dev_in_use[dev]) {
 195                 printk("VFS: put_unnamed_dev: freeing unused device %d/%d\n",
 196                                                         MAJOR(dev), MINOR(dev));
 197                 return;
 198         }
 199         unnamed_dev_in_use[dev] = 0;
 200 }
 201 
 202 static int do_umount(dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204         struct super_block * sb;
 205         int retval;
 206         
 207         if (dev==ROOT_DEV) {
 208                 /* Special case for "unmounting" root.  We just try to remount
 209                    it readonly, and sync() the device. */
 210                 if (!(sb=get_super(dev)))
 211                         return -ENOENT;
 212                 if (!(sb->s_flags & MS_RDONLY)) {
 213                         fsync_dev(dev);
 214                         retval = do_remount_sb(sb, MS_RDONLY, 0);
 215                         if (retval)
 216                                 return retval;
 217                 }
 218                 return 0;
 219         }
 220         if (!(sb=get_super(dev)) || !(sb->s_covered))
 221                 return -ENOENT;
 222         if (!sb->s_covered->i_mount)
 223                 printk("VFS: umount(%d/%d): mounted inode has i_mount=NULL\n",
 224                                                         MAJOR(dev), MINOR(dev));
 225         if (!fs_may_umount(dev, sb->s_mounted))
 226                 return -EBUSY;
 227         sb->s_covered->i_mount = NULL;
 228         iput(sb->s_covered);
 229         sb->s_covered = NULL;
 230         iput(sb->s_mounted);
 231         sb->s_mounted = NULL;
 232         if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
 233                 sb->s_op->write_super(sb);
 234         put_super(dev);
 235         return 0;
 236 }
 237 
 238 /*
 239  * Now umount can handle mount points as well as block devices.
 240  * This is important for filesystems which use unnamed block devices.
 241  *
 242  * There is a little kludge here with the dummy_inode.  The current
 243  * vfs release functions only use the r_dev field in the inode so
 244  * we give them the info they need without using a real inode.
 245  * If any other fields are ever needed by any block device release
 246  * functions, they should be faked here.  -- jrs
 247  */
 248 
 249 asmlinkage int sys_umount(char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
 250 {
 251         struct inode * inode;
 252         dev_t dev;
 253         int retval;
 254         struct inode dummy_inode;
 255         struct file_operations * fops;
 256 
 257         if (!suser())
 258                 return -EPERM;
 259         retval = namei(name,&inode);
 260         if (retval) {
 261                 retval = lnamei(name,&inode);
 262                 if (retval)
 263                         return retval;
 264         }
 265         if (S_ISBLK(inode->i_mode)) {
 266                 dev = inode->i_rdev;
 267                 if (IS_NODEV(inode)) {
 268                         iput(inode);
 269                         return -EACCES;
 270                 }
 271         } else {
 272                 if (!inode || !inode->i_sb || inode != inode->i_sb->s_mounted) {
 273                         iput(inode);
 274                         return -EINVAL;
 275                 }
 276                 dev = inode->i_sb->s_dev;
 277                 iput(inode);
 278                 memset(&dummy_inode, 0, sizeof(dummy_inode));
 279                 dummy_inode.i_rdev = dev;
 280                 inode = &dummy_inode;
 281         }
 282         if (MAJOR(dev) >= MAX_BLKDEV) {
 283                 iput(inode);
 284                 return -ENXIO;
 285         }
 286         if (!(retval = do_umount(dev)) && dev != ROOT_DEV) {
 287                 fops = get_blkfops(MAJOR(dev));
 288                 if (fops && fops->release)
 289                         fops->release(inode,NULL);
 290                 if (MAJOR(dev) == UNNAMED_MAJOR)
 291                         put_unnamed_dev(dev);
 292         }
 293         if (inode != &dummy_inode)
 294                 iput(inode);
 295         if (retval)
 296                 return retval;
 297         fsync_dev(dev);
 298         return 0;
 299 }
 300 
 301 /*
 302  * do_mount() does the actual mounting after sys_mount has done the ugly
 303  * parameter parsing. When enough time has gone by, and everything uses the
 304  * new mount() parameters, sys_mount() can then be cleaned up.
 305  *
 306  * We cannot mount a filesystem if it has active, used, or dirty inodes.
 307  * We also have to flush all inode-data for this device, as the new mount
 308  * might need new info.
 309  */
 310 static int do_mount(dev_t dev, const char * dir, char * type, int flags, void * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 311 {
 312         struct inode * dir_i;
 313         struct super_block * sb;
 314         int error;
 315 
 316         error = namei(dir,&dir_i);
 317         if (error)
 318                 return error;
 319         if (dir_i->i_count != 1 || dir_i->i_mount) {
 320                 iput(dir_i);
 321                 return -EBUSY;
 322         }
 323         if (!S_ISDIR(dir_i->i_mode)) {
 324                 iput(dir_i);
 325                 return -EPERM;
 326         }
 327         if (!fs_may_mount(dev)) {
 328                 iput(dir_i);
 329                 return -EBUSY;
 330         }
 331         sb = read_super(dev,type,flags,data,0);
 332         if (!sb || sb->s_covered) {
 333                 iput(dir_i);
 334                 return -EBUSY;
 335         }
 336         sb->s_covered = dir_i;
 337         dir_i->i_mount = sb->s_mounted;
 338         return 0;               /* we don't iput(dir_i) - see umount */
 339 }
 340 
 341 
 342 /*
 343  * Alters the mount flags of a mounted file system. Only the mount point
 344  * is used as a reference - file system type and the device are ignored.
 345  * FS-specific mount options can't be altered by remounting.
 346  */
 347 
 348 static int do_remount_sb(struct super_block *sb, int flags, char *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 349 {
 350         int retval;
 351         
 352         /* If we are remounting RDONLY, make sure there are no rw files open */
 353         if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
 354                 if (!fs_may_remount_ro(sb->s_dev))
 355                         return -EBUSY;
 356         if (sb->s_op && sb->s_op->remount_fs) {
 357                 retval = sb->s_op->remount_fs(sb, &flags, data);
 358                 if (retval)
 359                         return retval;
 360         }
 361         sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) |
 362                 (flags & MS_RMT_MASK);
 363         return 0;
 364 }
 365 
 366 static int do_remount(const char *dir,int flags,char *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 367 {
 368         struct inode *dir_i;
 369         int retval;
 370 
 371         retval = namei(dir,&dir_i);
 372         if (retval)
 373                 return retval;
 374         if (dir_i != dir_i->i_sb->s_mounted) {
 375                 iput(dir_i);
 376                 return -EINVAL;
 377         }
 378         retval = do_remount_sb(dir_i->i_sb, flags, data);
 379         iput(dir_i);
 380         return retval;
 381 }
 382 
 383 static int copy_mount_options (const void * data, unsigned long *where)
     /* [previous][next][first][last][top][bottom][index][help] */
 384 {
 385         int i;
 386         unsigned long page;
 387         struct vm_area_struct * vma;
 388 
 389         *where = 0;
 390         if (!data)
 391                 return 0;
 392 
 393         for (vma = current->mmap ; ; ) {
 394                 if (!vma ||
 395                     (unsigned long) data < vma->vm_start) {
 396                         return -EFAULT;
 397                 }
 398                 if ((unsigned long) data < vma->vm_end)
 399                         break;
 400                 vma = vma->vm_next;
 401         }
 402         i = vma->vm_end - (unsigned long) data;
 403         if (PAGE_SIZE <= (unsigned long) i)
 404                 i = PAGE_SIZE-1;
 405         if (!(page = __get_free_page(GFP_KERNEL))) {
 406                 return -ENOMEM;
 407         }
 408         memcpy_fromfs((void *) page,data,i);
 409         *where = page;
 410         return 0;
 411 }
 412 
 413 /*
 414  * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to
 415  * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
 416  *
 417  * data is a (void *) that can point to any structure up to
 418  * PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent
 419  * information (or be NULL).
 420  *
 421  * NOTE! As old versions of mount() didn't use this setup, the flags
 422  * has to have a special 16-bit magic number in the hight word:
 423  * 0xC0ED. If this magic word isn't present, the flags and data info
 424  * isn't used, as the syscall assumes we are talking to an older
 425  * version that didn't understand them.
 426  */
 427 asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
     /* [previous][next][first][last][top][bottom][index][help] */
 428         unsigned long new_flags, void * data)
 429 {
 430         struct file_system_type * fstype;
 431         struct inode * inode;
 432         struct file_operations * fops;
 433         dev_t dev;
 434         int retval;
 435         char * t;
 436         unsigned long flags = 0;
 437         unsigned long page = 0;
 438 
 439         if (!suser())
 440                 return -EPERM;
 441         if ((new_flags &
 442              (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) {
 443                 retval = copy_mount_options (data, &page);
 444                 if (retval < 0)
 445                         return retval;
 446                 retval = do_remount(dir_name,
 447                                     new_flags & ~MS_MGC_MSK & ~MS_REMOUNT,
 448                                     (char *) page);
 449                 free_page(page);
 450                 return retval;
 451         }
 452         retval = copy_mount_options (type, &page);
 453         if (retval < 0)
 454                 return retval;
 455         fstype = get_fs_type((char *) page);
 456         free_page(page);
 457         if (!fstype)            
 458                 return -ENODEV;
 459         t = fstype->name;
 460         if (fstype->requires_dev) {
 461                 retval = namei(dev_name,&inode);
 462                 if (retval)
 463                         return retval;
 464                 if (!S_ISBLK(inode->i_mode)) {
 465                         iput(inode);
 466                         return -ENOTBLK;
 467                 }
 468                 if (IS_NODEV(inode)) {
 469                         iput(inode);
 470                         return -EACCES;
 471                 }
 472                 dev = inode->i_rdev;
 473                 if (MAJOR(dev) >= MAX_BLKDEV) {
 474                         iput(inode);
 475                         return -ENXIO;
 476                 }
 477         } else {
 478                 if (!(dev = get_unnamed_dev()))
 479                         return -EMFILE;
 480                 inode = NULL;
 481         }
 482         fops = get_blkfops(MAJOR(dev));
 483         if (fops && fops->open) {
 484                 retval = fops->open(inode,NULL);
 485                 if (retval) {
 486                         iput(inode);
 487                         return retval;
 488                 }
 489         }
 490         page = 0;
 491         if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) {
 492                 flags = new_flags & ~MS_MGC_MSK;
 493                 retval = copy_mount_options(data, &page);
 494                 if (retval < 0) {
 495                         iput(inode);
 496                         return retval;
 497                 }
 498         }
 499         retval = do_mount(dev,dir_name,t,flags,(void *) page);
 500         free_page(page);
 501         if (retval && fops && fops->release)
 502                 fops->release(inode,NULL);
 503         iput(inode);
 504         return retval;
 505 }
 506 
 507 void mount_root(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 508 {
 509         struct file_system_type * fs_type;
 510         struct super_block * sb;
 511         struct inode * inode;
 512 
 513         memset(super_blocks, 0, sizeof(super_blocks));
 514         fcntl_init_locks();
 515         if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
 516                 printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
 517                 wait_for_keypress();
 518         }
 519         for (fs_type = file_systems; fs_type->read_super; fs_type++) {
 520                 if (!fs_type->requires_dev)
 521                         continue;
 522                 sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
 523                 if (sb) {
 524                         inode = sb->s_mounted;
 525                         inode->i_count += 3 ;   /* NOTE! it is logically used 4 times, not 1 */
 526                         sb->s_covered = inode;
 527                         sb->s_flags = root_mountflags;
 528                         current->pwd = inode;
 529                         current->root = inode;
 530                         printk ("VFS: Mounted root (%s filesystem)%s.\n",
 531                                 fs_type->name,
 532                                 (sb->s_flags & MS_RDONLY) ? " readonly" : "");
 533                         return;
 534                 }
 535         }
 536         panic("VFS: Unable to mount root");
 537 }

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