/****************************************************************************** * * axfs_do_fill_data_ptrs * * Description: * Fills the incore region descriptor with data from the onmedia version. * Processes the region to populate virt_addr by mapping to the physical * address or copying the data to RAM or if the data can be fetched later, * it is set to NULL. * * Parameters: * (IN) sb - pointer to the super block on media * * (IN) region_desc_offset - offset to the region descriptor from the * beginning of filesystem * * (OUT) iregion - pointer to the in RAM copy of the region descriptor * * (IN) force_va - if true the region must have a valid virt_addr * * Returns: * 0 or error number * *****************************************************************************/ static int axfs_do_fill_data_ptrs(struct super_block *sb, u64 region_desc_offset, struct axfs_region_desc_incore *iregion, int force_va) { struct axfs_super_incore *sbi; struct axfs_region_desc_onmedia *oregion; unsigned long addr; void *mapped = NULL; int err; u64 size; u64 end; u64 struct_len = sizeof(*oregion); sbi = AXFS_SB(sb); oregion = (struct axfs_region_desc_onmedia *) axfs_fetch_data(sb,region_desc_offset,struct_len); iregion->fsoffset = be64_to_cpu(oregion->fsoffset); iregion->size = be64_to_cpu(oregion->size); iregion->compressed_size = be64_to_cpu(oregion->compressed_size); iregion->max_index = be64_to_cpu(oregion->max_index); iregion->table_byte_depth = oregion->table_byte_depth; iregion->incore = oregion->incore; vfree(oregion); if (iregion->size == 0) return 0; end = iregion->fsoffset + iregion->size; if( (AXFS_IS_REGION_XIP(sbi,iregion)) && !(force_va && (sbi->mmap_size < end)) ) { if(AXFS_PHYSADDR_IS_VALID(sbi) ) { addr = sbi->phys_start_addr; addr += (unsigned long)iregion->fsoffset; size = (sbi->mmap_size > (iregion->fsoffset + iregion->size)) ? iregion->size : (sbi->mmap_size - iregion->fsoffset); iregion->virt_addr = AXFS_REMAP(addr,size); } else { addr = sbi->virt_start_addr; addr += (unsigned long)iregion->fsoffset; iregion->virt_addr = (void *)addr; } } else if(AXFS_IS_REGION_INCORE(iregion) || AXFS_IS_REGION_COMPRESSED(iregion) || force_va) { iregion->virt_addr = vmalloc(iregion->size); if(!(iregion->virt_addr)) { err = -ENOMEM; goto out; } if(AXFS_IS_REGION_COMPRESSED(iregion)) { mapped = axfs_fetch_data(sb,iregion->fsoffset,iregion->compressed_size); err = axfs_uncompress_block(iregion->virt_addr,iregion->size,mapped,iregion->compressed_size); if (err) goto out; } else { mapped = axfs_fetch_data(sb,iregion->fsoffset,iregion->size); memcpy(iregion->virt_addr,mapped,iregion->size); } } else { iregion->virt_addr = NULL; } if(mapped) vfree(mapped); return 0; out: if(mapped) vfree(mapped); if(iregion->virt_addr) vfree(iregion->virt_addr); return err; }
static int axfs_fill_region_data(struct super_block *sb, struct axfs_region_desc *region, int force) { struct axfs_super *sbi = AXFS_SB(sb); unsigned long addr; void *buff = NULL; void *vaddr; int err = -ENOMEM; u64 size = region->size; u64 fsoffset = region->fsoffset; u64 end = fsoffset + size; u64 c_size = region->compressed_size; if (size == 0) return 0; if (axfs_is_region_incore(region)) goto incore; if (axfs_is_region_compressed(region)) goto incore; if (axfs_is_region_xip(sbi, region)) { if ((end > sbi->mmap_size) && (force)) goto incore; addr = sbi->virt_start_addr; addr += (unsigned long)fsoffset; region->virt_addr = (void *)addr; return 0; } if (force) goto incore; region->virt_addr = NULL; return 0; incore: region->virt_addr = vmalloc(size); if (!region->virt_addr) goto out; vaddr = region->virt_addr; if (axfs_is_region_compressed(region)) { buff = vmalloc(c_size); if (!buff) goto out; axfs_copy_metadata(sb, buff, fsoffset, c_size); err = axfs_uncompress_block(vaddr, size, buff, c_size); if (!err) goto out; vfree(buff); } else { axfs_copy_metadata(sb, vaddr, fsoffset, size); } return 0; out: vfree(buff); vfree(region->virt_addr); return err; }