1 #include "fs.h" 2 #include "inode.h" 3 #include "super.h" 4 #include <minix/vfsif.h> 5 #include <minix/bdev.h> 6 7 /*===========================================================================* 8 * fs_mount * 9 *===========================================================================*/ 10 int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node, 11 unsigned int *res_flags) 12 { 13 /* This function reads the superblock of the partition, gets the root inode 14 * and sends back the details of them. 15 */ 16 struct inode *root_ip; 17 int r, readonly; 18 19 fs_dev = dev; 20 readonly = (flags & REQ_RDONLY) ? 1 : 0; 21 22 /* Open the device the file system lives on. */ 23 if (bdev_open(fs_dev, readonly ? BDEV_R_BIT : (BDEV_R_BIT|BDEV_W_BIT) ) != 24 OK) { 25 return(EINVAL); 26 } 27 28 /* Fill in the super block. */ 29 superblock.s_dev = fs_dev; /* read_super() needs to know which dev */ 30 r = read_super(&superblock); 31 32 /* Is it recognized as a Minix filesystem? */ 33 if (r != OK) { 34 superblock.s_dev = NO_DEV; 35 bdev_close(fs_dev); 36 return(r); 37 } 38 39 /* clean check: if rw and not clean, switch to readonly */ 40 if(!(superblock.s_flags & MFSFLAG_CLEAN) && !readonly) { 41 if(bdev_close(fs_dev) != OK) 42 panic("couldn't bdev_close after found unclean FS"); 43 readonly = 1; 44 45 if (bdev_open(fs_dev, BDEV_R_BIT) != OK) { 46 panic("couldn't bdev_open after found unclean FS"); 47 return(EINVAL); 48 } 49 printf("MFS: WARNING: FS 0x%llx unclean, mounting readonly\n", fs_dev); 50 } 51 52 lmfs_set_blocksize(superblock.s_block_size); 53 54 /* Compute the current number of used zones, and report it to libminixfs. 55 * Note that libminixfs really wants numbers of *blocks*, but this MFS 56 * implementation dropped support for differing zone/block sizes a while ago. 57 */ 58 used_zones = superblock.s_zones - count_free_bits(&superblock, ZMAP); 59 60 lmfs_set_blockusage(superblock.s_zones, used_zones); 61 62 /* Get the root inode of the mounted file system. */ 63 if( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NULL) { 64 printf("MFS: couldn't get root inode\n"); 65 superblock.s_dev = NO_DEV; 66 bdev_close(fs_dev); 67 return(EINVAL); 68 } 69 70 if(root_ip->i_mode == 0) { 71 printf("%s:%d zero mode for root inode?\n", __FILE__, __LINE__); 72 put_inode(root_ip); 73 superblock.s_dev = NO_DEV; 74 bdev_close(fs_dev); 75 return(EINVAL); 76 } 77 78 superblock.s_rd_only = readonly; 79 80 /* Root inode properties */ 81 root_node->fn_ino_nr = root_ip->i_num; 82 root_node->fn_mode = root_ip->i_mode; 83 root_node->fn_size = root_ip->i_size; 84 root_node->fn_uid = root_ip->i_uid; 85 root_node->fn_gid = root_ip->i_gid; 86 root_node->fn_dev = NO_DEV; 87 88 *res_flags = RES_NOFLAGS; 89 90 /* Mark it dirty */ 91 if(!superblock.s_rd_only) { 92 superblock.s_flags &= ~MFSFLAG_CLEAN; 93 if(write_super(&superblock) != OK) 94 panic("mounting: couldn't write dirty superblock"); 95 } 96 97 return(r); 98 } 99 100 101 /*===========================================================================* 102 * fs_mountpt * 103 *===========================================================================*/ 104 int fs_mountpt(ino_t ino_nr) 105 { 106 /* This function looks up the mount point, it checks the condition whether 107 * the partition can be mounted on the inode or not. 108 */ 109 register struct inode *rip; 110 int r = OK; 111 mode_t bits; 112 113 /* Temporarily open the file. */ 114 if( (rip = get_inode(fs_dev, ino_nr)) == NULL) 115 return(EINVAL); 116 117 if(rip->i_mountpoint) r = EBUSY; 118 119 /* It may not be special. */ 120 bits = rip->i_mode & I_TYPE; 121 if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR; 122 123 put_inode(rip); 124 125 if(r == OK) rip->i_mountpoint = TRUE; 126 127 return(r); 128 } 129 130 131 /*===========================================================================* 132 * fs_unmount * 133 *===========================================================================*/ 134 void fs_unmount(void) 135 { 136 /* Unmount a file system. */ 137 int count; 138 struct inode *rip, *root_ip; 139 140 /* See if the mounted device is busy. Only 1 inode using it should be 141 * open --the root inode-- and that inode only 1 time. This is an integrity 142 * check only: VFS expects the unmount to succeed either way. 143 */ 144 count = 0; 145 for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) 146 if (rip->i_count > 0 && rip->i_dev == fs_dev) count += rip->i_count; 147 if (count != 1) 148 printf("MFS: file system has %d in-use inodes!\n", count); 149 150 if ((root_ip = find_inode(fs_dev, ROOT_INODE)) == NULL) 151 panic("MFS: couldn't find root inode\n"); 152 153 put_inode(root_ip); 154 155 /* force any cached blocks out of memory */ 156 fs_sync(); 157 158 /* Mark it clean if we're allowed to write _and_ it was clean originally. */ 159 if (!superblock.s_rd_only) { 160 superblock.s_flags |= MFSFLAG_CLEAN; 161 write_super(&superblock); 162 } 163 164 /* Close the device the file system lives on. */ 165 bdev_close(fs_dev); 166 167 /* Throw out blocks out of the VM cache, to prevent corruption later. */ 168 lmfs_invalidate(fs_dev); 169 170 /* Finish off the unmount. */ 171 superblock.s_dev = NO_DEV; 172 } 173 174