Fork me on GitHub

root/kernel/syscalls/mount.c

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

DEFINITIONS

This source file includes following definitions.
  1. sys_mount

   1 /*
   2  * fiwix/kernel/syscalls/mount.c
   3  *
   4  * Copyright 2018, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/types.h>
   9 #include <fiwix/fs.h>
  10 #include <fiwix/stat.h>
  11 #include <fiwix/buffer.h>
  12 #include <fiwix/mman.h>
  13 #include <fiwix/filesystems.h>
  14 #include <fiwix/mm.h>
  15 #include <fiwix/errno.h>
  16 #include <fiwix/string.h>
  17 
  18 #ifdef __DEBUG__
  19 #include <fiwix/stdio.h>
  20 #include <fiwix/process.h>
  21 #endif /*__DEBUG__ */
  22 
  23 int sys_mount(const char *source, const char *target, const char *fstype, unsigned long int flags, const void *data)
  24 {
  25         struct inode *i_source, *i_target;
  26         struct mount *mt;
  27         struct filesystems *fs;
  28         struct vma *vma;
  29         char *tmp_source, *tmp_target, *tmp_fstype;
  30         __dev_t dev;
  31         int len, errno;
  32 
  33 #ifdef __DEBUG__
  34         printk("(pid %d) sys_mount(%s, %s, %s, 0x%08x, 0x%08x\n", current->pid, source, target, (int)fstype ? fstype : "<NULL>", flags, data);
  35 #endif /* __DEBUG__ */
  36 
  37         if(!IS_SUPERUSER) {
  38                 return -EPERM;
  39         }
  40 
  41         if((errno = malloc_name(target, &tmp_target)) < 0) {
  42                 return errno;
  43         }
  44         if((errno = namei(tmp_target, &i_target, NULL, FOLLOW_LINKS))) {
  45                 free_name(tmp_target);
  46                 return errno;
  47         }
  48         if(!S_ISDIR(i_target->i_mode)) {
  49                 iput(i_target);
  50                 free_name(tmp_target);
  51                 return -ENOTDIR;
  52         }
  53         if((flags & MS_MGC_VAL) == MS_MGC_VAL) {
  54                 flags &= ~MS_MGC_MSK;
  55         }
  56 
  57         if(flags & MS_REMOUNT) {
  58                 if(!(mt = get_mount_point(i_target))) {
  59                         iput(i_target);
  60                         free_name(tmp_target);
  61                         return -EINVAL;
  62                 }
  63                 fs = mt->fs;
  64                 if(fs->fsop && fs->fsop->remount_fs) {
  65                         if((errno = fs->fsop->remount_fs(&mt->sb, flags))) {
  66                                 iput(i_target);
  67                                 free_name(tmp_target);
  68                                 return errno;
  69                         }
  70                 } else {
  71                         iput(i_target);
  72                         free_name(tmp_target);
  73                         return -EINVAL;
  74                 }
  75 
  76                 /* switching from RW to RO */
  77                 if(flags & MS_RDONLY && !(mt->sb.flags & MS_RDONLY)) {
  78                         dev = mt->dev;
  79                         /* 
  80                          * FIXME: if there are files opened in RW mode then
  81                          * we can't continue and must return -EBUSY.
  82                          */
  83                         if(fs->fsop && fs->fsop->release_superblock) {
  84                                 fs->fsop->release_superblock(&mt->sb);
  85                         }
  86                         sync_superblocks(dev);
  87                         sync_inodes(dev);
  88                         sync_buffers(dev);
  89                 }
  90 
  91                 mt->sb.flags &= ~MS_RDONLY;
  92                 mt->sb.flags |= (flags & MS_RDONLY);
  93                 iput(i_target);
  94                 free_name(tmp_target);
  95                 return 0;
  96         }
  97 
  98         if(i_target->mount_point) {
  99                 iput(i_target);
 100                 free_name(tmp_target);
 101                 return -EBUSY;
 102         }
 103 
 104         /* check the validity of fstype */
 105         if(!(vma = find_vma_region((unsigned int)fstype))) {
 106                 iput(i_target);
 107                 free_name(tmp_target);
 108                 return -EFAULT;
 109         }
 110         if(!(vma->prot & PROT_READ)) {
 111                 iput(i_target);
 112                 free_name(tmp_target);
 113                 return -EFAULT;
 114         }
 115         len = MIN(vma->end - (unsigned int)fstype, PAGE_SIZE - 1);
 116         if(!(tmp_fstype = (char *)kmalloc())) {
 117                 iput(i_target);
 118                 free_name(tmp_target);
 119                 return -ENOMEM;
 120         }
 121         memcpy_b(tmp_fstype, fstype, len);
 122 
 123         if(!(fs = get_filesystem(fstype))) {
 124                 iput(i_target);
 125                 free_name(tmp_target);
 126                 free_name(tmp_fstype);
 127                 return -ENODEV;
 128         }
 129         dev = fs->fsop->fsdev;
 130 
 131         if((errno = malloc_name(source, &tmp_source)) < 0) {
 132                 iput(i_target);
 133                 free_name(tmp_target);
 134                 free_name(tmp_fstype);
 135                 return errno;
 136         }
 137         if(fs->fsop->flags == FSOP_REQUIRES_DEV) {
 138                 if((errno = namei(tmp_source, &i_source, NULL, FOLLOW_LINKS))) {
 139                         iput(i_target);
 140                         free_name(tmp_target);
 141                         free_name(tmp_fstype);
 142                         free_name(tmp_source);
 143                         return errno;
 144                 }
 145                 if(!S_ISBLK(i_source->i_mode)) {
 146                         iput(i_target);
 147                         iput(i_source);
 148                         free_name(tmp_target);
 149                         free_name(tmp_fstype);
 150                         free_name(tmp_source);
 151                         return -ENOTBLK;
 152                 }
 153                 if(i_source->fsop && i_source->fsop->open) {
 154                         if((errno = i_source->fsop->open(i_source, NULL))) {
 155                                 iput(i_target);
 156                                 iput(i_source);
 157                                 free_name(tmp_target);
 158                                 free_name(tmp_fstype);
 159                                 free_name(tmp_source);
 160                                 return errno;
 161                         }
 162                 } else {
 163                         iput(i_target);
 164                         iput(i_source);
 165                         free_name(tmp_target);
 166                         free_name(tmp_fstype);
 167                         free_name(tmp_source);
 168                         return -EINVAL;
 169                 }
 170                 dev = i_source->rdev;
 171         }
 172 
 173         if(!(mt = get_free_mount_point(dev))) {
 174                 if(fs->fsop->flags == FSOP_REQUIRES_DEV) {
 175                         i_source->fsop->close(i_source, NULL);
 176                         iput(i_source);
 177                 }
 178                 iput(i_target);
 179                 free_name(tmp_target);
 180                 free_name(tmp_fstype);
 181                 free_name(tmp_source);
 182                 return -EBUSY;
 183         }
 184 
 185         mt->sb.flags = flags;
 186         if(fs->fsop && fs->fsop->read_superblock) {
 187                 if((errno = fs->fsop->read_superblock(dev, &mt->sb))) {
 188                         i_source->fsop->close(i_source, NULL);
 189                         if(fs->fsop->flags == FSOP_REQUIRES_DEV) {
 190                                 iput(i_source);
 191                         }
 192                         iput(i_target);
 193                         release_mount_point(mt);
 194                         free_name(tmp_target);
 195                         free_name(tmp_fstype);
 196                         free_name(tmp_source);
 197                         return errno;
 198                 }
 199         } else {
 200                 if(fs->fsop->flags == FSOP_REQUIRES_DEV) {
 201                         iput(i_source);
 202                 }
 203                 iput(i_target);
 204                 release_mount_point(mt);
 205                 free_name(tmp_target);
 206                 free_name(tmp_fstype);
 207                 free_name(tmp_source);
 208                 return -EINVAL;
 209         }
 210 
 211         mt->dev = dev;
 212         strncpy(mt->devname, tmp_source, DEVNAME_MAX);
 213         strcpy(mt->dirname, tmp_target);
 214         mt->sb.dir = i_target;
 215         mt->fs = fs;
 216         i_target->mount_point = mt->sb.root;
 217         free_name(tmp_target);
 218         free_name(tmp_fstype);
 219         free_name(tmp_source);
 220         return 0;
 221 }

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