Welcome to The Fiwix Project
A UNIX-like kernel for the i386 architecture
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 }