Fork me on GitHub

root/fs/super.c

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

DEFINITIONS

This source file includes following definitions.
  1. superblock_lock
  2. superblock_unlock
  3. get_free_mount_point
  4. release_mount_point
  5. get_mount_point
  6. get_superblock
  7. sync_superblocks
  8. kern_mount
  9. mount_root
  10. mount_init

   1 /*
   2  * fiwix/fs/super.c
   3  *
   4  * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/asm.h>
   9 #include <fiwix/kernel.h>
  10 #include <fiwix/types.h>
  11 #include <fiwix/errno.h>
  12 #include <fiwix/fs.h>
  13 #include <fiwix/stat.h>
  14 #include <fiwix/filesystems.h>
  15 #include <fiwix/sleep.h>
  16 #include <fiwix/sched.h>
  17 #include <fiwix/stdio.h>
  18 #include <fiwix/string.h>
  19 
  20 struct mount *mount_table;
  21 static struct resource sync_resource = { NULL, NULL };
  22 
  23 void superblock_lock(struct superblock *sb)
  24 {
  25         unsigned long int flags;
  26 
  27         for(;;) {
  28                 SAVE_FLAGS(flags); CLI();
  29                 if(sb->locked) {
  30                         sb->wanted = 1;
  31                         RESTORE_FLAGS(flags);
  32                         sleep(&superblock_lock, PROC_UNINTERRUPTIBLE);
  33                 } else {
  34                         break;
  35                 }
  36         }
  37         sb->locked = 1;
  38         RESTORE_FLAGS(flags);
  39 }
  40  
  41 void superblock_unlock(struct superblock *sb)
  42 {
  43         unsigned long int flags;
  44 
  45         SAVE_FLAGS(flags); CLI();
  46         sb->locked = 0;
  47         if(sb->wanted) {
  48                 sb->wanted = 0;
  49                 wakeup(&superblock_lock);
  50         }
  51         RESTORE_FLAGS(flags);
  52 }
  53 
  54 struct mount * get_free_mount_point(__dev_t dev)
  55 {
  56         unsigned long int flags;
  57         int n;
  58 
  59         if(!dev) {
  60                 printk("%s(): invalid device %d,%d.\n", __FUNCTION__, MAJOR(dev), MINOR(dev));
  61                 return NULL;
  62         }
  63 
  64         for(n = 0; n < NR_MOUNT_POINTS; n++) {
  65                 if(mount_table[n].dev == dev) {
  66                         printk("%s(): device %d,%d already mounted.\n", __FUNCTION__, MAJOR(dev), MINOR(dev));
  67                         return NULL;
  68                 }
  69         }
  70 
  71         SAVE_FLAGS(flags); CLI();
  72         for(n = 0; n < NR_MOUNT_POINTS; n++) {
  73                 if(!mount_table[n].used) {
  74                         /* 'dev' is saved here now for get_superblock() (which
  75                          * in turn is called by read_inode(), which in turn is
  76                          * called by iget(), which in turn is called by
  77                          * read_superblock) to be able to find the device.
  78                          */
  79                         mount_table[n].dev = dev; 
  80                         mount_table[n].used = 1;
  81                         RESTORE_FLAGS(flags);
  82                         return &mount_table[n];
  83                 }
  84         }
  85         RESTORE_FLAGS(flags);
  86 
  87         printk("WARNING: %s(): mount-point table is full.\n", __FUNCTION__);
  88         return NULL;
  89 }
  90 
  91 void release_mount_point(struct mount *mt)
  92 {
  93         memset_b(mt, NULL, sizeof(struct mount));
  94 }
  95 
  96 struct mount * get_mount_point(struct inode *i_target)
  97 {
  98         int n;
  99 
 100         for(n = 0; n < NR_MOUNT_POINTS; n++) {
 101                 if(mount_table[n].used) {
 102                         if(S_ISDIR(i_target->i_mode)) {
 103                                 if(mount_table[n].sb.root == i_target) {
 104                                         return &mount_table[n];
 105                                 }
 106                         }
 107                         if(S_ISBLK(i_target->i_mode)) {
 108                                 if(mount_table[n].dev == i_target->rdev) {
 109                                         return &mount_table[n];
 110                                 }
 111                         }
 112                 }
 113         }
 114         return NULL;
 115 }
 116 
 117 struct superblock * get_superblock(__dev_t dev)
 118 {
 119         int n;
 120 
 121         for(n = 0; n < NR_MOUNT_POINTS; n++) {
 122                 if(mount_table[n].used && mount_table[n].dev == dev) {
 123                         return &mount_table[n].sb;
 124                 }
 125         }
 126         return NULL;
 127 }
 128 
 129 void sync_superblocks(__dev_t dev)
 130 {
 131         struct superblock *sb;
 132         int n, errno;
 133 
 134         lock_resource(&sync_resource);
 135         for(n = 0; n < NR_MOUNT_POINTS; n++) {
 136                 if(mount_table[n].used && (!dev || mount_table[n].dev == dev)) {
 137                         sb = &mount_table[n].sb;
 138                         if(sb->dirty && !(sb->flags & MS_RDONLY)) {
 139                                 if(sb->fsop && sb->fsop->write_superblock) {
 140                                         errno = sb->fsop->write_superblock(sb);
 141                                         if(errno) {
 142                                                 printk("WARNING: %s(): I/O error on device %d,%d while syncing superblock.\n", __FUNCTION__, MAJOR(sb->dev), MINOR(sb->dev));
 143                                         }
 144                                 }
 145                         }
 146                 }
 147         }
 148         unlock_resource(&sync_resource);
 149 }
 150 
 151 /* pseudo-filesystems are only mountable by the kernel */
 152 int kern_mount(__dev_t dev, struct filesystems *fs)
 153 {
 154         struct mount *mt;
 155 
 156         if(!(mt = get_free_mount_point(dev))) {
 157                 return -EBUSY;
 158         }
 159 
 160         if(fs->fsop->read_superblock(dev, &mt->sb)) {
 161                 release_mount_point(mt);
 162                 return -EINVAL;
 163         }
 164 
 165         mt->dev = dev;
 166         strcpy(mt->devname, "none");
 167         strcpy(mt->dirname, "none");
 168         mt->sb.dir = NULL;
 169         mt->fs = fs;
 170         fs->mt = mt;
 171         return 0;
 172 }
 173 
 174 int mount_root(void)
 175 {
 176         struct filesystems *fs;
 177         struct mount *mt;
 178 
 179         /* FIXME: before trying to mount the filesystem, we should first
 180          * check if '_rootdev' is a device successfully registered.
 181          */
 182 
 183         if(!_rootdev) {
 184                 PANIC("root device not defined.\n");
 185         }
 186 
 187         if(!(fs = get_filesystem(_rootfstype))) {
 188                 printk("WARNING: %s(): '%s' is not a registered filesystem. Defaulting to 'minix'.\n", __FUNCTION__, _rootfstype);
 189                 if(!(fs = get_filesystem("minix"))) {
 190                         PANIC("minix filesystem is not registered!\n");
 191                 }
 192         }
 193 
 194         if(!(mt = get_free_mount_point(_rootdev))) {
 195                 PANIC("unable to get a free mount point.\n");
 196         }
 197 
 198         mt->sb.flags = MS_RDONLY;
 199         if(fs->fsop && fs->fsop->read_superblock) {
 200                 if(fs->fsop->read_superblock(_rootdev, &mt->sb)) {
 201                         PANIC("unable to mount root filesystem on %s.\n", _rootdevname);
 202                 }
 203         }
 204 
 205         strcpy(mt->devname, "/dev/root");
 206         strcpy(mt->dirname, "/");
 207         mt->dev = _rootdev;
 208         mt->sb.root->mount_point = mt->sb.root;
 209         mt->sb.root->count++;
 210         mt->sb.dir = mt->sb.root;
 211         mt->sb.dir->count++;
 212         mt->fs = fs;
 213 
 214         current->root = mt->sb.root;
 215         current->root->count++;
 216         current->pwd = mt->sb.root;
 217         current->pwd->count++;
 218         iput(mt->sb.root);
 219 
 220         printk("mounted root device (%s filesystem) in readonly mode.\n", fs->name);
 221         return 0;
 222 }
 223 
 224 void mount_init(void)
 225 {
 226         memset_b(mount_table, NULL, mount_table_size);
 227 }

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