int fs_format(fs_t* fs) { if (fs == NULL) { printf("[fs] argument is null.\n"); return -1; } // erase all blocks char null_block[BLOCK_SIZE]; memset(null_block,0,sizeof(null_block)); for (int i = 0; i < block_num_blocks(fs->blocks); i++) { block_write(fs->blocks,i,null_block); } // reserve file system meta data blocks BMAP_SET(fs->blk_bmap,0); BMAP_SET(fs->blk_bmap,1); for (int i = 0; i < ITAB_NUM_BLKS; i++) { BMAP_SET(fs->blk_bmap,i+2); } // reserve inodes 0 (will never be used) and 1 (the root) BMAP_SET(fs->inode_bmap,0); BMAP_SET(fs->inode_bmap,1); fsi_inode_init(&fs->inode_tab[1],FS_DIR); // save the file system metadata fsi_store_fsdata(fs); return 0; }
static int cbm_write(struct exfat_dev* dev) { uint32_t allocated_clusters = DIV_ROUND_UP(cbm.get_size(), get_cluster_size()) + DIV_ROUND_UP(uct.get_size(), get_cluster_size()) + DIV_ROUND_UP(rootdir.get_size(), get_cluster_size()); size_t bitmap_size = DIV_ROUND_UP(allocated_clusters, CHAR_BIT); bitmap_t* bitmap = malloc(BMAP_SIZE(bitmap_size)); size_t i; if (bitmap == NULL) { exfat_error("failed to allocate bitmap of %zu bytes", BMAP_SIZE(bitmap_size)); return 1; } memset(bitmap, 0, BMAP_SIZE(bitmap_size)); for (i = 0; i < bitmap_size * CHAR_BIT; i++) if (i < allocated_clusters) BMAP_SET(bitmap, i); if (exfat_write(dev, bitmap, bitmap_size) < 0) { free(bitmap); exfat_error("failed to write bitmap of %zu bytes", bitmap_size); return 1; } free(bitmap); return 0; }
/* * Identify memory proximity domains and hot-remove capabilities. * Fill node memory chunk list structure. */ static void __init parse_memory_affinity_structure (char *sratp) { unsigned long long paddr, size; unsigned long start_pfn, end_pfn; u8 pxm; struct node_memory_chunk_s *p, *q, *pend; struct acpi_srat_mem_affinity *memory_affinity = (struct acpi_srat_mem_affinity *) sratp; if ((memory_affinity->flags & ACPI_SRAT_MEM_ENABLED) == 0) return; /* empty entry */ pxm = memory_affinity->proximity_domain & 0xff; /* mark this node as "seen" in node bitmap */ BMAP_SET(pxm_bitmap, pxm); /* calculate info for memory chunk structure */ paddr = memory_affinity->base_address; size = memory_affinity->length; start_pfn = paddr >> PAGE_SHIFT; end_pfn = (paddr + size) >> PAGE_SHIFT; if (num_memory_chunks >= MAXCHUNKS) { printk("Too many mem chunks in SRAT. Ignoring %lld MBytes at %llx\n", size/(1024*1024), paddr); return; } /* Insertion sort based on base address */ pend = &node_memory_chunk[num_memory_chunks]; for (p = &node_memory_chunk[0]; p < pend; p++) { if (start_pfn < p->start_pfn) break; } if (p < pend) { for (q = pend; q >= p; q--) *(q + 1) = *q; } p->start_pfn = start_pfn; p->end_pfn = end_pfn; p->pxm = pxm; num_memory_chunks++; printk("Memory range 0x%lX to 0x%lX (type 0x%X) in proximity domain 0x%02X %s\n", start_pfn, end_pfn, memory_affinity->memory_type, pxm, ((memory_affinity->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ? "enabled and removable" : "enabled" ) ); }
static cluster_t find_bit_and_set(uint8_t* bitmap, cluster_t start, cluster_t end) { const cluster_t mid_start = (start + 7) / 8 * 8; const cluster_t mid_end = end / 8 * 8; cluster_t c; cluster_t byte; for (c = start; c < mid_start; c++) if (BMAP_GET(bitmap, c) == 0) { BMAP_SET(bitmap, c); return c + EXFAT_FIRST_DATA_CLUSTER; } for (byte = mid_start / 8; byte < mid_end / 8; byte++) if (bitmap[byte] != 0xff) { cluster_t bit; for (bit = 0; bit < 8; bit++) if (!(bitmap[byte] & (1u << bit))) { bitmap[byte] |= (1u << bit); return byte * 8 + bit + EXFAT_FIRST_DATA_CLUSTER; } } for (c = mid_end; c < end; c++) if (BMAP_GET(bitmap, c) == 0) { BMAP_SET(bitmap, c); return c + EXFAT_FIRST_DATA_CLUSTER; } return EXFAT_CLUSTER_END; }
/* Identify CPU proximity domains */ static void __init parse_cpu_affinity_structure(char *p) { struct acpi_srat_cpu_affinity *cpu_affinity = (struct acpi_srat_cpu_affinity *) p; if ((cpu_affinity->flags & ACPI_SRAT_CPU_ENABLED) == 0) return; /* empty entry */ /* mark this node as "seen" in node bitmap */ BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain_lo); apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain_lo; printk("CPU 0x%02X in proximity domain 0x%02X\n", cpu_affinity->apic_id, cpu_affinity->proximity_domain_lo); }
static cluster_t find_bit_and_set(uint8_t* bitmap, size_t start, size_t end) { const size_t start_index = start / 8; const size_t end_index = DIV_ROUND_UP(end, 8); size_t i; size_t c; for (i = start_index; i < end_index; i++) { if (bitmap[i] == 0xff) continue; for (c = MAX(i * 8, start); c < MIN((i + 1) * 8, end); c++) if (BMAP_GET(bitmap, c) == 0) { BMAP_SET(bitmap, c); return c + EXFAT_FIRST_DATA_CLUSTER; } } return EXFAT_CLUSTER_END; }
/* Identify CPU proximity domains */ void __init acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *cpu_affinity) { if (srat_disabled()) return; if (cpu_affinity->header.length != sizeof(struct acpi_srat_cpu_affinity)) { bad_srat(); return; } if ((cpu_affinity->flags & ACPI_SRAT_CPU_ENABLED) == 0) return; /* empty entry */ /* mark this node as "seen" in node bitmap */ BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain_lo); apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain_lo; printk(KERN_DEBUG "CPU %02x in proximity domain %02x\n", cpu_affinity->apic_id, cpu_affinity->proximity_domain_lo); }
static cluster_t find_bit_and_set(bitmap_t* bitmap, size_t start, size_t end) { const size_t start_index = start / sizeof(bitmap_t) / 8; const size_t end_index = DIV_ROUND_UP(end, sizeof(bitmap_t) * 8); size_t i; size_t start_bitindex; size_t end_bitindex; size_t c; for (i = start_index; i < end_index; i++) { if (bitmap[i] == ~((bitmap_t) 0)) continue; start_bitindex = MAX(i * sizeof(bitmap_t) * 8, start); end_bitindex = MIN((i + 1) * sizeof(bitmap_t) * 8, end); for (c = start_bitindex; c < end_bitindex; c++) if (BMAP_GET(bitmap, c) == 0) { BMAP_SET(bitmap, c); return c + EXFAT_FIRST_DATA_CLUSTER; } } return EXFAT_CLUSTER_END; }
/* * Identify memory proximity domains and hot-remove capabilities. * Fill node memory chunk list structure. */ void __init acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *memory_affinity) { unsigned long long paddr, size; unsigned long start_pfn, end_pfn; u8 pxm; struct node_memory_chunk_s *p, *q, *pend; if (srat_disabled()) return; if (memory_affinity->header.length != sizeof(struct acpi_srat_mem_affinity)) { bad_srat(); return; } if ((memory_affinity->flags & ACPI_SRAT_MEM_ENABLED) == 0) return; /* empty entry */ pxm = memory_affinity->proximity_domain & 0xff; /* mark this node as "seen" in node bitmap */ BMAP_SET(pxm_bitmap, pxm); /* calculate info for memory chunk structure */ paddr = memory_affinity->base_address; size = memory_affinity->length; start_pfn = paddr >> PAGE_SHIFT; end_pfn = (paddr + size) >> PAGE_SHIFT; if (num_memory_chunks >= MAXCHUNKS) { printk(KERN_WARNING "Too many mem chunks in SRAT." " Ignoring %lld MBytes at %llx\n", size/(1024*1024), paddr); return; } /* Insertion sort based on base address */ pend = &node_memory_chunk[num_memory_chunks]; for (p = &node_memory_chunk[0]; p < pend; p++) { if (start_pfn < p->start_pfn) break; } if (p < pend) { for (q = pend; q >= p; q--) *(q + 1) = *q; } p->start_pfn = start_pfn; p->end_pfn = end_pfn; p->pxm = pxm; num_memory_chunks++; printk(KERN_DEBUG "Memory range %08lx to %08lx" " in proximity domain %02x %s\n", start_pfn, end_pfn, pxm, ((memory_affinity->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ? "enabled and removable" : "enabled" ) ); }
int fs_mkdir(fs_t* fs, inodeid_t dir, char* newdir, inodeid_t* newdirid) { if (fs==NULL || dir>=ITAB_SIZE || newdir==NULL || newdirid==NULL) { printf("[fs_mkdir] malformed arguments.\n"); return -1; } if (strlen(newdir) == 0 || strlen(newdir)+1 > FS_MAX_FNAME_SZ){ dprintf("[fs_mkdir] directory size error.\n"); return -1; } if (!BMAP_ISSET(fs->inode_bmap,dir)) { dprintf("[fs_mkdir] inode is not being used.\n"); return -1; } fs_inode_t* idir = &fs->inode_tab[dir]; if (idir->type != FS_DIR) { dprintf("[fs_mkdir] inode is not a directory.\n"); return -1; } if (fsi_dir_search(fs,dir,newdir,newdirid) == 0) { dprintf("[fs_mkdir] directory already exists.\n"); return -1; } // check if there are free inodes unsigned finode; if (!fsi_bmap_find_free(fs->inode_bmap,ITAB_SIZE,&finode)) { dprintf("[fs_mkdir] there are no free inodes.\n"); return -1; } // add a new block to the directory if necessary if (idir->size % BLOCK_SIZE == 0) { unsigned fblock; if (!fsi_bmap_find_free(fs->blk_bmap,block_num_blocks(fs->blocks),&fblock)) { dprintf("[fs_mkdir] no free blocks to augment directory.\n"); return -1; } BMAP_SET(fs->blk_bmap,fblock); idir->blocks[idir->size / BLOCK_SIZE] = fblock; } // add the entry to the directory fs_dentry_t page[DIR_PAGE_ENTRIES]; block_read(fs->blocks,idir->blocks[idir->size/BLOCK_SIZE],(char*)page); fs_dentry_t* entry = &page[idir->size % BLOCK_SIZE / sizeof(fs_dentry_t)]; strcpy(entry->name,newdir); entry->inodeid = finode; block_write(fs->blocks,idir->blocks[idir->size/BLOCK_SIZE],(char*)page); idir->size += sizeof(fs_dentry_t); // reserve and init the new file inode BMAP_SET(fs->inode_bmap,finode); fsi_inode_init(&fs->inode_tab[finode],FS_DIR); // save the file system metadata fsi_store_fsdata(fs); *newdirid = finode; return 0; }
int fs_write(fs_t* fs, inodeid_t file, unsigned offset, unsigned count, char* buffer) { if (fs == NULL || file >= ITAB_SIZE || buffer == NULL) { dprintf("[fs_write] malformed arguments.\n"); return -1; } if (!BMAP_ISSET(fs->inode_bmap,file)) { dprintf("[fs_write] inode is not being used.\n"); return -1; } fs_inode_t* ifile = &fs->inode_tab[file]; if (ifile->type != FS_FILE) { dprintf("[fs_write] inode is not a file.\n"); return -1; } if (offset > ifile->size) { offset = ifile->size; } unsigned *blk; int blks_used = OFFSET_TO_BLOCKS(ifile->size); int blks_req = MAX(OFFSET_TO_BLOCKS(offset+count),blks_used)-blks_used; dprintf("[fs_write] count=%d, offset=%d, fsize=%d, bused=%d, breq=%d\n", count,offset,ifile->size,blks_used,blks_req); if (blks_req > 0) { if(blks_req > INODE_NUM_BLKS-blks_used) { dprintf("[fs_write] no free block entries in inode.\n"); return -1; } dprintf("[fs_write] required %d blocks, used %d\n", blks_req, blks_used); // check and reserve if there are free blocks for (int i = blks_used; i < blks_used + blks_req; i++) { if(i < INODE_NUM_BLKS) blk = &ifile->blocks[i]; if (!fsi_bmap_find_free(fs->blk_bmap,block_num_blocks(fs->blocks),blk)) { // ITAB_SIZE dprintf("[fs_write] there are no free blocks.\n"); return -1; } BMAP_SET(fs->blk_bmap, *blk); dprintf("[fs_write] block %d allocated.\n", *blk); } } char block[BLOCK_SIZE]; int num = 0, pos; int iblock = offset/BLOCK_SIZE; // write within the existent blocks while (num < count && iblock < blks_used) { if(iblock < INODE_NUM_BLKS) { blk = ifile->blocks; pos = iblock; } block_read(fs->blocks, blk[pos], block); int start = ((num == 0)?(offset % BLOCK_SIZE):0); for (int i = start; i < BLOCK_SIZE && num < count; i++, num++) { block[i] = buffer[num]; } block_write(fs->blocks, blk[pos], block); iblock++; } dprintf("[fs_write] written %d bytes within.\n", num); // write within the allocated blocks while (num < count && iblock < blks_used + blks_req) { if(iblock < INODE_NUM_BLKS) { blk = ifile->blocks; pos = iblock; } for (int i = 0; i < BLOCK_SIZE && num < count; i++, num++) { block[i] = buffer[num]; } block_write(fs->blocks, blk[pos], block); iblock++; } if (num != count) { printf("[fs_write] severe error: num=%d != count=%d!\n", num, count); exit(-1); } ifile->size = MAX(offset + count, ifile->size); // update the inode in disk fsi_store_fsdata(fs); dprintf("[fs_write] written %d bytes, file size %d.\n", count, ifile->size); return 0; }