1 #include "fs.h" 2 #include "inode.h" 3 #include "super.h" 4 #include <minix/vfsif.h> 5 #include <minix/bdev.h> 6 7 static int cleanmount = 1; 8 9 /*===========================================================================* 10 * fs_readsuper * 11 *===========================================================================*/ 12 int fs_readsuper() 13 { 14 /* This function reads the superblock of the partition, gets the root inode 15 * and sends back the details of them. Note, that the FS process does not 16 * know the index of the vmnt object which refers to it, whenever the pathname 17 * lookup leaves a partition an ELEAVEMOUNT error is transferred back 18 * so that the VFS knows that it has to find the vnode on which this FS 19 * process' partition is mounted on. 20 */ 21 struct inode *root_ip; 22 cp_grant_id_t label_gid; 23 size_t label_len; 24 int r; 25 int readonly, isroot; 26 27 fs_dev = fs_m_in.m_vfs_fs_readsuper.device; 28 label_gid = fs_m_in.m_vfs_fs_readsuper.grant; 29 label_len = fs_m_in.m_vfs_fs_readsuper.path_len; 30 readonly = (fs_m_in.m_vfs_fs_readsuper.flags & REQ_RDONLY) ? 1 : 0; 31 isroot = (fs_m_in.m_vfs_fs_readsuper.flags & REQ_ISROOT) ? 1 : 0; 32 33 if (label_len > sizeof(fs_dev_label)) 34 return(EINVAL); 35 36 r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0, 37 (vir_bytes) fs_dev_label, label_len); 38 if (r != OK) { 39 printf("MFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r); 40 return(EINVAL); 41 } 42 43 /* Map the driver label for this major. */ 44 bdev_driver(fs_dev, fs_dev_label); 45 46 /* Open the device the file system lives on. */ 47 if (bdev_open(fs_dev, readonly ? BDEV_R_BIT : (BDEV_R_BIT|BDEV_W_BIT) ) != 48 OK) { 49 return(EINVAL); 50 } 51 52 /* Fill in the super block. */ 53 superblock.s_dev = fs_dev; /* read_super() needs to know which dev */ 54 r = read_super(&superblock); 55 56 /* Is it recognized as a Minix filesystem? */ 57 if (r != OK) { 58 superblock.s_dev = NO_DEV; 59 bdev_close(fs_dev); 60 return(r); 61 } 62 63 /* Remember whether we were mounted cleanly so we know what to 64 * do at unmount time 65 */ 66 if(superblock.s_flags & MFSFLAG_CLEAN) 67 cleanmount = 1; 68 69 /* clean check: if rw and not clean, switch to readonly */ 70 if(!(superblock.s_flags & MFSFLAG_CLEAN) && !readonly) { 71 if(bdev_close(fs_dev) != OK) 72 panic("couldn't bdev_close after found unclean FS"); 73 readonly = 1; 74 75 if (bdev_open(fs_dev, BDEV_R_BIT) != OK) { 76 panic("couldn't bdev_open after found unclean FS"); 77 return(EINVAL); 78 } 79 printf("MFS: WARNING: FS 0x%llx unclean, mounting readonly\n", fs_dev); 80 } 81 82 lmfs_set_blocksize(superblock.s_block_size, major(fs_dev)); 83 84 /* Get the root inode of the mounted file system. */ 85 if( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NULL) { 86 printf("MFS: couldn't get root inode\n"); 87 superblock.s_dev = NO_DEV; 88 bdev_close(fs_dev); 89 return(EINVAL); 90 } 91 92 if(root_ip->i_mode == 0) { 93 printf("%s:%d zero mode for root inode?\n", __FILE__, __LINE__); 94 put_inode(root_ip); 95 superblock.s_dev = NO_DEV; 96 bdev_close(fs_dev); 97 return(EINVAL); 98 } 99 100 superblock.s_rd_only = readonly; 101 superblock.s_is_root = isroot; 102 103 /* Root inode properties */ 104 fs_m_out.m_fs_vfs_readsuper.inode = root_ip->i_num; 105 fs_m_out.m_fs_vfs_readsuper.mode = root_ip->i_mode; 106 fs_m_out.m_fs_vfs_readsuper.file_size = root_ip->i_size; 107 fs_m_out.m_fs_vfs_readsuper.uid = root_ip->i_uid; 108 fs_m_out.m_fs_vfs_readsuper.gid = root_ip->i_gid; 109 fs_m_out.m_fs_vfs_readsuper.flags = RES_HASPEEK; 110 111 /* Mark it dirty */ 112 if(!superblock.s_rd_only) { 113 superblock.s_flags &= ~MFSFLAG_CLEAN; 114 if(write_super(&superblock) != OK) 115 panic("mounting: couldn't write dirty superblock"); 116 } 117 118 return(r); 119 } 120 121 122 /*===========================================================================* 123 * fs_mountpoint * 124 *===========================================================================*/ 125 int fs_mountpoint() 126 { 127 /* This function looks up the mount point, it checks the condition whether 128 * the partition can be mounted on the inode or not. 129 */ 130 register struct inode *rip; 131 int r = OK; 132 mode_t bits; 133 134 /* Temporarily open the file. */ 135 if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_mountpoint.inode)) == NULL) 136 return(EINVAL); 137 138 139 if(rip->i_mountpoint) r = EBUSY; 140 141 /* It may not be special. */ 142 bits = rip->i_mode & I_TYPE; 143 if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR; 144 145 put_inode(rip); 146 147 if(r == OK) rip->i_mountpoint = TRUE; 148 149 return(r); 150 } 151 152 153 /*===========================================================================* 154 * fs_unmount * 155 *===========================================================================*/ 156 int fs_unmount() 157 { 158 /* Unmount a file system by device number. */ 159 int count; 160 struct inode *rip, *root_ip; 161 162 if(superblock.s_dev != fs_dev) return(EINVAL); 163 164 /* See if the mounted device is busy. Only 1 inode using it should be 165 * open --the root inode-- and that inode only 1 time. */ 166 count = 0; 167 for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) 168 if (rip->i_count > 0 && rip->i_dev == fs_dev) count += rip->i_count; 169 170 if ((root_ip = find_inode(fs_dev, ROOT_INODE)) == NULL) { 171 panic("MFS: couldn't find root inode\n"); 172 return(EINVAL); 173 } 174 175 if (count > 1) return(EBUSY); /* can't umount a busy file system */ 176 put_inode(root_ip); 177 178 /* force any cached blocks out of memory */ 179 (void) fs_sync(); 180 181 /* Mark it clean if we're allowed to write _and_ it was clean originally. */ 182 if(cleanmount && !superblock.s_rd_only) { 183 superblock.s_flags |= MFSFLAG_CLEAN; 184 write_super(&superblock); 185 } 186 187 /* Close the device the file system lives on. */ 188 bdev_close(fs_dev); 189 190 /* Throw out blocks out of the VM cache, to prevent corruption later. */ 191 lmfs_invalidate(fs_dev); 192 193 /* Finish off the unmount. */ 194 superblock.s_dev = NO_DEV; 195 unmountdone = TRUE; 196 197 return(OK); 198 } 199 200