func (c *server_InodeTbl) loadInode(xp *common.Inode) { // The count at this point is guaranteed to be > 0, so the device cannot // be unmounted until the load has completed and the inode has been 'put' inum := xp.Inum - 1 info := xp.Devinfo inodes_per_block := info.Blocksize / common.V2_INODE_SIZE ioffset := inum % inodes_per_block blocknum := info.MapOffset + (inum / inodes_per_block) // Load the inode from the disk and create an in-memory version of it bp := c.bcache.GetBlock(info.Devnum, blocknum, common.INODE_BLOCK, common.NORMAL) inodeb := bp.Block.(common.InodeBlock) // We have the full block, now get the correct inode entry inode_d := &inodeb[ioffset] xp.Disk_Inode = inode_d xp.Dirty = false xp.Mounted = nil }
func (fs *FileSystem) do_mount(proc *Process, dev common.BlockDevice, path string) error { if dev == nil { return common.EINVAL } // scan bitmap block table to see if 'dev' is already mounted found := false freeIndex := -1 for i := 0; i < common.NR_DEVICES; i++ { if fs.devices[i] == dev { found = true } else if fs.devices[i] == nil { freeIndex = i } } if found { return common.EBUSY // already mounted } if freeIndex == -1 { return common.ENFILE // no device slot available } // Invalidate the cache for this index to be sure fs.bcache.Invalidate(freeIndex) // Fill in the device info devinfo, err := common.GetDeviceInfo(dev) // If it a recognized Minix filesystem if err != nil { return err } // Create a new allocation table for this device alloc := alloctbl.NewAllocTbl(devinfo, fs.bcache, freeIndex) // Update the device number/alloc table devinfo.Devnum = freeIndex devinfo.AllocTbl = alloc // Add the device to the block cache/inode table fs.bcache.MountDevice(freeIndex, dev, devinfo) fs.itable.MountDevice(freeIndex, devinfo) fs.devices[freeIndex] = dev fs.devinfo[freeIndex] = devinfo // Get the inode of the file to be mounted on rip, err := fs.eatPath(fs.procs[common.ROOT_PROCESS], path) if err != nil { // Perform lots of cleanup fs.devices[freeIndex] = nil fs.devinfo[freeIndex] = nil fs.bcache.UnmountDevice(freeIndex) fs.itable.UnmountDevice(freeIndex) return err } var r error = nil // It may not be busy if rip.Count > 1 { r = common.EBUSY } // It may not be spacial bits := rip.Type() if bits == common.I_BLOCK_SPECIAL || bits == common.I_CHAR_SPECIAL { r = common.ENOTDIR } // Get the root inode of the mounted file system var root_ip *common.Inode if r == nil { root_ip, err = fs.itable.GetInode(freeIndex, common.ROOT_INODE) if err != nil { r = err } } if root_ip != nil && root_ip.Mode == 0 { r = common.EINVAL } // File types of 'rip' and 'root_ip' may not conflict if r == nil { if !rip.IsDirectory() && root_ip.IsDirectory() { r = common.EISDIR } } // If error, return the bitmap and both inodes; release the maps if r != nil { // TODO: Refactor this error handling code? // Perform lots of cleanup fs.devices[freeIndex] = nil fs.devinfo[freeIndex] = nil fs.bcache.UnmountDevice(freeIndex) fs.itable.UnmountDevice(freeIndex) return r } // Nothing else can go wrong, so perform the mount minfo := &common.MountInfo{ MountPoint: rip, MountTarget: root_ip, } rip.Mounted = minfo // so we can find the root inode during lookup root_ip.Mounted = minfo // so we can easily resolve from a mount target to the mount point // Store the mountinfo in the device info table for easy mapping devinfo.MountInfo = minfo return nil }