The Pedigree Project 0.1
Ext2InodeAllocation.cc
1/* Copyright (c) 2026, Pedigree Developers. */
2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/machine/Disk.h"
4#include "pedigree/kernel/syscallError.h"
5#include "pedigree/kernel/utilities/Vector.h"
6#include "pedigree/kernel/utilities/utility.h"
7
8#include "Ext2Filesystem.h"
9#include "ext2.h"
10
11uint32_t Ext2Filesystem::findFreeInode(uint32_t uid, uint32_t gid) {
12#if THREADS || defined(STANDALONE_MUTEXES)
14#endif
15 const uint32_t perGroup = LITTLE_TO_HOST32(m_pSuperblock->s_inodes_per_group);
16 const uint32_t total = LITTLE_TO_HOST32(m_pSuperblock->s_inodes_count);
17 for (size_t group = 0; group < m_nGroupDescriptors; ++group) {
18 GroupDesc* descriptor = m_pGroupDescriptors[group];
19 if (!LITTLE_TO_HOST16(descriptor->bg_free_inodes_count)) {
20 continue;
21 }
22 if (!ensureFreeInodeBitmapLoaded(group)) {
23 return 0;
24 }
25 Vector<size_t>& bitmap = m_pInodeBitmaps[group];
26 for (uint32_t index = 0; index < perGroup; ++index) {
27 const uint64_t number = static_cast<uint64_t>(group) * perGroup + index + 1;
28 if (number > 0xffffffffULL || (total && number > total)) {
29 break;
30 }
31 const size_t field = (index / 8) / m_BlockSize;
32 auto* byte = reinterpret_cast<uint8_t*>(bitmap[field] + (index / 8) % m_BlockSize);
33 const uint8_t bit = 1U << (index % 8);
34 if (*byte & bit) {
35 continue;
36 }
37 Inode* inode = getInode(static_cast<uint32_t>(number));
38 if (!inode) {
39 return 0;
40 }
41 const uint32_t generation = LITTLE_TO_HOST32(inode->i_generation);
42 if (generation == 0xffffffffU) {
43 // Reusing this slot would revive a previously exported handle.
44 continue;
45 }
46
47 // Decode checks the same allocation lock and rejects links==0. Publish
48 // the new generation before allocation, keeping creation private until
49 // the directory insertion publishes its first link.
50 if (!quotaSucceeded(m_Quota.create(static_cast<uint32_t>(number), uid, gid)))
51 return 0;
52 ByteSet(inode, 0, m_InodeSize);
53 Ext2Owner::setUid(*inode, uid);
54 Ext2Owner::setGid(*inode, gid);
55 inode->i_generation = HOST_TO_LITTLE32(generation + 1);
56 writeInode(static_cast<uint32_t>(number));
57 *byte |= bit;
58 descriptor->bg_free_inodes_count =
59 HOST_TO_LITTLE16(LITTLE_TO_HOST16(descriptor->bg_free_inodes_count) - 1);
60 m_pSuperblock->s_free_inodes_count =
61 HOST_TO_LITTLE32(LITTLE_TO_HOST32(m_pSuperblock->s_free_inodes_count) - 1);
62 m_pDisk->write(1024ULL);
63 writeBlock(LITTLE_TO_HOST32(descriptor->bg_inode_bitmap) + field);
64 const uint32_t descriptors = LITTLE_TO_HOST32(m_pSuperblock->s_first_data_block) + 1;
65 writeBlock(descriptors + (group * sizeof(GroupDesc)) / m_BlockSize);
66 return static_cast<uint32_t>(number);
67 }
68 }
69 SYSCALL_ERROR(NoSpaceLeftOnDevice);
70 return 0;
71}
virtual void write(uint64_t location)
Definition Disk.cc:340
size_t m_nGroupDescriptors
GroupDesc ** m_pGroupDescriptors
void writeBlock(uint32_t block)
Vector< size_t > * m_pInodeBitmaps
Superblock * m_pSuperblock
Disk * m_pDisk
Definition Filesystem.h:188
A vector / dynamic array.
Definition Vector.h:33
Definition ext2.h:152