Fork me on GitHub

root/kernel/syscalls/umount2.c

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

DEFINITIONS

This source file includes following definitions.
  1. sys_umount2

   1 /*
   2  * fiwix/kernel/syscalls/umount2.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/filesystems.h>
  11 #include <fiwix/stat.h>
  12 #include <fiwix/sleep.h>
  13 #include <fiwix/devices.h>
  14 #include <fiwix/buffer.h>
  15 #include <fiwix/errno.h>
  16 #include <fiwix/stdio.h>
  17 #include <fiwix/string.h>
  18 
  19 static struct resource umount_resource = { NULL, NULL };
  20 
  21 int sys_umount2(const char *target, int flags)
  22 {
  23         struct inode *i_target;
  24         struct mount *mt = NULL;
  25         struct filesystems *fs;
  26         struct device *d;
  27         struct inode dummy_i;
  28         struct superblock *sb;
  29         char *tmp_target;
  30         __dev_t dev;
  31         int errno;
  32 
  33 #ifdef __DEBUG__
  34         printk("(pid %d) sys_umount2(%s, 0x%08x)\n", current->pid, target, flags);
  35 #endif /*__DEBUG__ */
  36 
  37         if(!IS_SUPERUSER) {
  38                 return -EPERM;
  39         }
  40         if((errno = malloc_name(target, &tmp_target)) < 0) {
  41                 return errno;
  42         }
  43         if((errno = namei(tmp_target, &i_target, NULL, FOLLOW_LINKS))) {
  44                 free_name(tmp_target);
  45                 return errno;
  46         }
  47         if(!S_ISBLK(i_target->i_mode) && !S_ISDIR(i_target->i_mode)) {
  48                 iput(i_target);
  49                 free_name(tmp_target);
  50                 return -EINVAL;
  51         }
  52 
  53         if(!(mt = get_mount_point(i_target))) {
  54                 iput(i_target);
  55                 free_name(tmp_target);
  56                 return -EINVAL;
  57         }
  58         if(S_ISBLK(i_target->i_mode)) {
  59                 dev = i_target->rdev;
  60         } else {
  61                 dev = i_target->sb->dev;
  62         }
  63 
  64         if(!(sb = get_superblock(dev))) {
  65                 printk("WARNING: %s(): unable to get superblock from device %d,%d\n", __FUNCTION__, MAJOR(dev), MINOR(dev));
  66                 iput(i_target);
  67                 free_name(tmp_target);
  68                 return -EINVAL;
  69         }
  70 
  71         /*
  72          * We must free now the inode in order to avoid having its 'count' to 2
  73          * when calling check_fs_busy(), specially if sys_umount() was called
  74          * using the mount-point instead of the device.
  75          */
  76         iput(i_target);
  77         free_name(tmp_target);
  78 
  79         if(check_fs_busy(dev, sb->root)) {
  80                 return -EBUSY;
  81         }
  82 
  83         lock_resource(&umount_resource);
  84 
  85         fs = mt->fs;
  86         if(fs->fsop && fs->fsop->release_superblock) {
  87                 fs->fsop->release_superblock(sb);
  88         }
  89         if(sb->fsop->flags & FSOP_REQUIRES_DEV) {
  90                 if(!(d = get_device(BLK_DEV, dev))) {
  91                         printk("WARNING: %s(): block device %d,%d not registered!\n", __FUNCTION__, MAJOR(dev), MINOR(dev));
  92                         unlock_resource(&umount_resource);
  93                         return -EINVAL;
  94                 }
  95                 memset_b(&dummy_i, 0, sizeof(struct inode));
  96                 dummy_i.dev = dummy_i.rdev = dev;
  97                 if(d && d->fsop && d->fsop->close) {
  98                         d->fsop->close(&dummy_i, NULL);
  99                 }
 100         }
 101 
 102         sb->dir->mount_point = NULL;
 103         iput(sb->root);
 104         iput(sb->dir);
 105 
 106         sync_superblocks(dev);
 107         sync_inodes(dev);
 108         sync_buffers(dev);
 109         invalidate_buffers(dev);
 110         invalidate_inodes(dev);
 111 
 112         release_mount_point(mt);
 113         unlock_resource(&umount_resource);
 114         return 0;
 115 }

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