Kernel: Changed stat values from func to be field

- Removed virtual functions for all of the stat stuff.
This did however introduce some issues, mainly with /proc
becoming out of sync if you changed your ID. I propose we
do the linux thing and just have a stat update function
which is optional, but allows dynamic updates of stat fields
for cases such as those in uid/gid in /proc.
- Simplified the API, although still kind of annoying
it is a bit simpler.
- Moved some of the FS structure from having the FS inode inside
the in memory inode to a Serialise <-> Deserialise model where
Inodes are deserialised from disk into in memory ones and then
back into on disk ones when it comes time for syncing.
This makes it semantically better in my opinion, as it explicitly
separates disk and non-disk functionality.
This commit is contained in:
2026-05-15 20:39:51 +03:00
committed by Bananymous
parent bf2121e166
commit 647d6a273d
47 changed files with 393 additions and 419 deletions

View File

@@ -281,7 +281,7 @@ namespace Kernel
auto& inode = inode_buffer.span().slice(inode_location.offset).as<Ext2::Inode>();
#if EXT2_VERIFY_NO_BLOCKS
static const char zero_buffer[sizeof(inode.block)] {};
ASSERT(memcmp(inode.block, zero_buffer, sizeof(inode.block)) == 0);
ASSERT(memcmp(inode.block.block, zero_buffer, sizeof(inode.block)) == 0);
#endif
bool is_directory = Inode::Mode(inode.mode).ifdir();
memset(&inode, 0x00, m_superblock.inode_size);

View File

@@ -10,14 +10,31 @@
namespace Kernel
{
blksize_t Ext2Inode::blksize() const
Ext2Inode::Ext2Inode(Ext2FS& fs, Ext2::Inode inode, uint32_t ino)
: m_fs(fs)
, m_ext2_blocks(inode.block)
, m_og_dtime(inode.dtime)
, m_og_flags(inode.flags)
, m_og_osd1(inode.osd1)
, m_og_generation(inode.generation)
, m_og_file_acl(inode.file_acl)
, m_og_dir_acl(inode.dir_acl)
, m_og_faddr(inode.faddr)
, m_og_osd2(inode.osd2)
{
return m_fs.block_size();
}
blkcnt_t Ext2Inode::blocks() const
{
return m_inode.blocks / (2 << m_fs.superblock().log_block_size);
m_ino = ino;
m_mode = inode.mode;
m_nlink = inode.links_count;
m_uid = inode.uid;
m_gid = inode.gid;
m_size = inode.size;
m_atime = timespec { .tv_sec = inode.atime, .tv_nsec = 0 };
m_mtime = timespec { .tv_sec = inode.mtime, .tv_nsec = 0 };
m_ctime = timespec { .tv_sec = inode.ctime, .tv_nsec = 0 };
m_dev = 0;
m_rdev = 0;
m_blksize = fs.block_size();
m_blocks = inode.blocks / (2 << fs.superblock().log_block_size);
}
uint32_t Ext2Inode::block_group() const
@@ -45,7 +62,7 @@ namespace Kernel
Ext2Inode::~Ext2Inode()
{
if (m_inode.links_count > 0)
if (m_nlink > 0)
return;
if (auto ret = cleanup_from_fs_no_lock(); ret.is_error())
dwarnln("Could not cleanup inode from FS: {}", ret.error());
@@ -58,7 +75,6 @@ namespace Kernel
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate)
{
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
if (block == 0 && !allocate)
@@ -69,7 +85,7 @@ namespace Kernel
if (block == 0)
{
block = TRY(m_fs.reserve_free_block(block_group()));
m_inode.blocks += inode_blocks_per_fs_block;
m_blocks++;
auto block_buffer = TRY(m_fs.get_block_buffer());
memset(block_buffer.data(), 0x00, block_buffer.size());
@@ -88,7 +104,7 @@ namespace Kernel
else
{
block = TRY(m_fs.reserve_free_block(block_group()));
m_inode.blocks += inode_blocks_per_fs_block;
m_blocks++;
memset(block_buffer.data(), 0, block_buffer.size());
@@ -112,13 +128,12 @@ namespace Kernel
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate)
{
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
const uint32_t indices_per_block = blksize() / sizeof(uint32_t);
if (data_block_index < 12)
{
if (m_inode.block[data_block_index] != 0)
return BAN::Optional<uint32_t>(m_inode.block[data_block_index]);
if (m_ext2_blocks.block[data_block_index] != 0)
return BAN::Optional<uint32_t>(m_ext2_blocks.block[data_block_index]);
if (!allocate)
return BAN::Optional<uint32_t>();
@@ -128,23 +143,23 @@ namespace Kernel
const auto block = TRY(m_fs.reserve_free_block(block_group()));
TRY(m_fs.write_block(block, block_buffer));
m_inode.block[data_block_index] = block;
m_inode.blocks += inode_blocks_per_fs_block;
m_ext2_blocks.block[data_block_index] = block;
m_blocks++;
return BAN::Optional<uint32_t>(block);
}
data_block_index -= 12;
if (data_block_index < indices_per_block)
return block_from_indirect_block_no_lock(m_inode.block[12], data_block_index, 1, allocate);
return block_from_indirect_block_no_lock(m_ext2_blocks.block[12], data_block_index, 1, allocate);
data_block_index -= indices_per_block;
if (data_block_index < indices_per_block * indices_per_block)
return block_from_indirect_block_no_lock(m_inode.block[13], data_block_index, 2, allocate);
return block_from_indirect_block_no_lock(m_ext2_blocks.block[13], data_block_index, 2, allocate);
data_block_index -= indices_per_block * indices_per_block;
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
return block_from_indirect_block_no_lock(m_inode.block[14], data_block_index, 3, allocate);
return block_from_indirect_block_no_lock(m_ext2_blocks.block[14], data_block_index, 3, allocate);
ASSERT_NOT_REACHED();
}
@@ -155,15 +170,15 @@ namespace Kernel
RWLockRDGuard _(m_lock);
if (m_inode.size < sizeof(m_inode.block))
if (static_cast<size_t>(m_size) < sizeof(m_ext2_blocks.block))
{
BAN::String result;
TRY(result.append(BAN::StringView(reinterpret_cast<const char*>(m_inode.block), m_inode.size)));
TRY(result.append(BAN::StringView(reinterpret_cast<const char*>(m_ext2_blocks.block), m_size)));
return result;
}
BAN::String result;
TRY(result.resize(m_inode.size));
TRY(result.resize(m_size));
TRY(read_impl(0, { reinterpret_cast<uint8_t*>(result.data()), result.size() }));
return BAN::move(result);
}
@@ -173,13 +188,13 @@ namespace Kernel
ASSERT(mode().iflnk());
RWLockWRGuard _(m_lock);
if (target.size() < sizeof(m_inode.block))
if (target.size() < sizeof(m_ext2_blocks.block))
{
if (m_inode.size >= sizeof(m_inode.block))
if (static_cast<size_t>(m_size) >= sizeof(m_ext2_blocks.block))
TRY(cleanup_data_blocks_no_lock());
memset(m_inode.block, 0, sizeof(m_inode.block));
memcpy(m_inode.block, target.data(), target.size());
m_inode.size = target.size();
memset(m_ext2_blocks.block, 0, sizeof(m_ext2_blocks.block));
memcpy(m_ext2_blocks.block, target.data(), target.size());
m_size = target.size();
TRY(sync_no_lock());
return {};
}
@@ -201,14 +216,14 @@ namespace Kernel
RWLockRDGuard _0(m_lock);
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= m_inode.size)
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= static_cast<size_t>(m_size))
return 0;
ScopedSync _1(*this);
uint32_t count = buffer.size();
if (offset + buffer.size() > m_inode.size)
count = m_inode.size - offset;
if (offset + buffer.size() > static_cast<size_t>(m_size))
count = m_size - offset;
const uint32_t block_size = blksize();
@@ -249,7 +264,7 @@ namespace Kernel
RWLockWRGuard _0(m_lock);
if (m_inode.size < offset + buffer.size())
if (static_cast<size_t>(m_size) < offset + buffer.size())
TRY(truncate_impl(offset + buffer.size()));
ScopedSync _(*this);
@@ -311,17 +326,17 @@ namespace Kernel
{
RWLockWRGuard _(m_lock);
if (m_inode.size == new_size)
if (static_cast<size_t>(m_size) == new_size)
return {};
// TODO: we should remove unused blocks on shrink
const auto old_size = m_inode.size;
const auto old_size = static_cast<size_t>(m_size);
m_inode.size = new_size;
m_size = new_size;
if (auto ret = sync_no_lock(); ret.is_error())
{
m_inode.size = old_size;
m_size = old_size;
return ret.release_error();
}
@@ -334,15 +349,15 @@ namespace Kernel
RWLockWRGuard _(m_lock);
if (m_inode.mode == mode)
if (m_mode == mode)
return {};
const auto old_mode = m_inode.mode;
const auto old_mode = m_mode.load();
m_inode.mode = (m_inode.mode & Inode::Mode::TYPE_MASK) | mode;
m_mode = (m_mode & Inode::Mode::TYPE_MASK) | mode;
if (auto ret = sync_no_lock(); ret.is_error())
{
m_inode.mode = old_mode;
m_mode = old_mode;
return ret.release_error();
}
@@ -353,18 +368,18 @@ namespace Kernel
{
RWLockWRGuard _(m_lock);
if (m_inode.uid == uid && m_inode.gid == gid)
if (m_uid == uid && m_gid == gid)
return {};
const auto old_uid = m_inode.uid;
const auto old_gid = m_inode.gid;
const auto old_uid = m_uid.load();
const auto old_gid = m_gid.load();
m_inode.uid = uid;
m_inode.gid = gid;
m_uid = uid;
m_gid = gid;
if (auto ret = sync_no_lock(); ret.is_error())
{
m_inode.uid = old_uid;
m_inode.gid = old_gid;
m_uid = old_uid;
m_gid = old_gid;
return ret.release_error();
}
@@ -376,19 +391,19 @@ namespace Kernel
RWLockWRGuard _(m_lock);
const uint32_t old_times[2] {
m_inode.atime,
m_inode.mtime,
static_cast<uint32_t>(m_atime.tv_sec),
static_cast<uint32_t>(m_mtime.tv_sec),
};
if (times[0].tv_nsec != UTIME_OMIT)
m_inode.atime = times[0].tv_sec;
m_atime.tv_sec = times[0].tv_sec;
if (times[1].tv_nsec != UTIME_OMIT)
m_inode.mtime = times[1].tv_sec;
m_mtime.tv_sec = times[1].tv_sec;
if (auto ret = sync_no_lock(); ret.is_error())
{
m_inode.atime = old_times[0];
m_inode.mtime = old_times[1];
m_atime.tv_sec = old_times[0];
m_mtime.tv_sec = old_times[1];
return ret.release_error();
}
@@ -432,25 +447,25 @@ namespace Kernel
BAN::ErrorOr<void> Ext2Inode::cleanup_data_blocks_no_lock()
{
if (mode().iflnk() && (size_t)size() < sizeof(m_inode.block))
if (mode().iflnk() && (size_t)size() < sizeof(m_ext2_blocks.block))
goto done;
// cleanup direct blocks
for (uint32_t i = 0; i < 12; i++)
if (m_inode.block[i])
TRY(m_fs.release_block(m_inode.block[i]));
if (m_ext2_blocks.block[i])
TRY(m_fs.release_block(m_ext2_blocks.block[i]));
// cleanup indirect blocks
if (m_inode.block[12])
TRY(cleanup_indirect_block_no_lock(m_inode.block[12], 1));
if (m_inode.block[13])
TRY(cleanup_indirect_block_no_lock(m_inode.block[13], 2));
if (m_inode.block[14])
TRY(cleanup_indirect_block_no_lock(m_inode.block[14], 3));
if (m_ext2_blocks.block[12])
TRY(cleanup_indirect_block_no_lock(m_ext2_blocks.block[12], 1));
if (m_ext2_blocks.block[13])
TRY(cleanup_indirect_block_no_lock(m_ext2_blocks.block[13], 2));
if (m_ext2_blocks.block[14])
TRY(cleanup_indirect_block_no_lock(m_ext2_blocks.block[14], 3));
done:
// mark blocks as deleted
memset(m_inode.block, 0x00, sizeof(m_inode.block));
memset(m_ext2_blocks.block, 0x00, sizeof(m_ext2_blocks.block));
TRY(sync_no_lock());
@@ -459,7 +474,7 @@ done:
BAN::ErrorOr<void> Ext2Inode::cleanup_from_fs_no_lock()
{
ASSERT(m_inode.links_count == 0);
ASSERT(m_nlink == 0);
TRY(cleanup_data_blocks_no_lock());
TRY(m_fs.delete_inode(ino()));
return {};
@@ -694,7 +709,7 @@ done:
if (name.size() > 255)
return BAN::Error::from_errno(ENAMETOOLONG);
if (m_inode.flags & Ext2::Enum::INDEX_FL)
if (m_og_flags & Ext2::Enum::INDEX_FL)
{
dwarnln("file creation to indexed directory not supported");
return BAN::Error::from_errno(ENOTSUP);
@@ -731,7 +746,7 @@ done:
new_entry.file_type = file_type;
memcpy(new_entry.name, name.data(), name.size());
inode.m_inode.links_count++;
inode.m_nlink++;
TRY(inode.sync_no_lock());
return {};
@@ -782,7 +797,7 @@ done:
needs_new_block:
block_index = TRY(fs_block_of_data_block_index_no_lock(data_block_count, true)).value();
m_inode.size += blksize();
m_size += blksize();
memset(block_buffer.data(), 0x00, block_buffer.size());
TRY(write_inode(0, block_size));
@@ -830,7 +845,7 @@ needs_new_block:
auto block_buffer = TRY(m_fs.get_block_buffer());
if (m_inode.flags & Ext2::Enum::INDEX_FL)
if (m_og_flags & Ext2::Enum::INDEX_FL)
{
dwarnln("deletion of indexed directory is not supported");
return BAN::Error::from_errno(ENOTSUP);
@@ -856,13 +871,13 @@ needs_new_block:
if (entry_name == "."_sv)
{
m_inode.links_count--;
m_nlink--;
TRY(sync_no_lock());
}
else if (entry_name == ".."_sv)
{
auto parent = TRY(Ext2Inode::create(m_fs, entry.inode));
parent->m_inode.links_count--;
parent->m_nlink--;
TRY(parent->sync_no_lock());
}
else
@@ -888,7 +903,7 @@ needs_new_block:
auto block_buffer = TRY(m_fs.get_block_buffer());
if (m_inode.flags & Ext2::Enum::INDEX_FL)
if (m_og_flags & Ext2::Enum::INDEX_FL)
{
dwarnln("deletion from indexed directory is not supported");
return BAN::Error::from_errno(ENOTSUP);
@@ -918,7 +933,7 @@ needs_new_block:
if (inode->nlink() == 0)
dprintln("Corrupted filesystem. Deleting inode with 0 links");
else
inode->m_inode.links_count--;
inode->m_nlink--;
TRY(sync_no_lock());
@@ -955,9 +970,29 @@ needs_new_block:
auto block_buffer = TRY(m_fs.get_block_buffer());
TRY(m_fs.read_block(inode_location.block, block_buffer));
if (memcmp(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode)))
Ext2::Inode inode {
.mode = static_cast<uint16_t>(m_mode),
.uid = static_cast<uint16_t>(m_uid),
.size = static_cast<uint32_t>(m_size),
.atime = static_cast<uint32_t>(m_atime.tv_sec),
.ctime = static_cast<uint32_t>(m_ctime.tv_sec),
.mtime = static_cast<uint32_t>(m_mtime.tv_sec),
.dtime = m_og_dtime,
.gid = static_cast<uint16_t>(m_gid),
.links_count = static_cast<uint16_t>(m_nlink),
.blocks = static_cast<uint32_t>(m_blocks * (blksize() / 512)),
.flags = m_og_flags,
.osd1 = m_og_osd1,
.block = m_ext2_blocks,
.generation = m_og_generation,
.file_acl = m_og_file_acl,
.dir_acl = m_og_dir_acl,
.faddr = m_og_faddr,
.osd2 = m_og_osd2
};
if (memcmp(block_buffer.data() + inode_location.offset, &inode, sizeof(Ext2::Inode)))
{
memcpy(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode));
memcpy(block_buffer.data() + inode_location.offset, &inode, sizeof(Ext2::Inode));
TRY(m_fs.write_block(inode_location.block, block_buffer));
}
@@ -996,5 +1031,4 @@ needs_new_block:
return BAN::Error::from_errno(ENOENT);
}
}

View File

@@ -23,27 +23,30 @@ namespace Kernel
return BAN::to_unix_time(ban_time);
}
blksize_t FATInode::blksize() const
static timespec fat_date_to_timespec(FAT::Date date, FAT::Time time)
{
return m_fs.inode_block_size(this);
}
timespec FATInode::atime() const
{
const time_t epoch = fat_date_to_epoch(m_entry.last_access_date, {});
const time_t epoch = fat_date_to_epoch(date, time);
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
}
timespec FATInode::mtime() const
FATInode::FATInode(FATFS& fs, const FAT::DirectoryEntry& entry, ino_t ino, uint32_t block_count)
: m_fs(fs)
, m_entry(entry)
, m_block_count(block_count)
{
const time_t epoch = fat_date_to_epoch(m_entry.write_date, m_entry.write_time);
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
}
timespec FATInode::ctime() const
{
const time_t epoch = fat_date_to_epoch(m_entry.creation_date, m_entry.creation_time);
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
m_ino = ino;
m_mode = ((m_entry.attr & FAT::FileAttr::DIRECTORY) ? Mode::IFDIR : Mode::IFREG) | 0777;
m_nlink = 1;
m_uid = 0;
m_gid = 0;
m_size = m_entry.file_size;
m_blksize = fs.inode_block_size(this);
m_atime = fat_date_to_timespec(m_entry.last_access_date, {});
m_mtime = fat_date_to_timespec(m_entry.write_date, m_entry.write_time);
m_ctime = fat_date_to_timespec(m_entry.creation_date, m_entry.creation_time);
m_blocks = m_block_count;
m_dev = 0;
m_rdev = 0;
}
const FileSystem* FATInode::filesystem() const

View File

@@ -5,14 +5,14 @@
namespace Kernel
{
BAN::ErrorOr<BAN::RefPtr<FileSystem>> FileSystem::from_block_device(BAN::RefPtr<BlockDevice> block_device)
{
if (auto res = Ext2FS::probe(block_device); !res.is_error() && res.value())
return BAN::RefPtr<FileSystem>(TRY(Ext2FS::create(block_device)));
if (auto res = FATFS::probe(block_device); !res.is_error() && res.value())
return BAN::RefPtr<FileSystem>(TRY(FATFS::create(block_device)));
dprintln("Unsupported filesystem");
return BAN::Error::from_errno(ENOTSUP);
}
BAN::ErrorOr<BAN::RefPtr<FileSystem>> FileSystem::from_block_device(BAN::RefPtr<BlockDevice> block_device)
{
if (auto res = Ext2FS::probe(block_device); !res.is_error() && res.value())
return BAN::RefPtr<FileSystem>(TRY(Ext2FS::create(block_device)));
if (auto res = FATFS::probe(block_device); !res.is_error() && res.value())
return BAN::RefPtr<FileSystem>(TRY(FATFS::create(block_device)));
dprintln("Unsupported filesystem");
return BAN::Error::from_errno(ENOTSUP);
}
}

View File

@@ -23,13 +23,22 @@ namespace Kernel
}
Pipe::Pipe(const Credentials& credentials)
: m_uid(credentials.euid())
, m_gid(credentials.egid())
{
timespec current_time = SystemTimer::get().real_time();
m_atime = current_time;
m_mtime = current_time;
m_ctime = current_time;
m_uid = credentials.euid();
m_gid = credentials.egid();
m_ino = 0; // FIXME
m_mode = { Mode::IFIFO | Mode::IRUSR | Mode::IWUSR };
m_nlink = 1;
m_size = 0;
m_blksize = 4096;
m_blocks = 0;
m_dev = 0; // FIXME
m_rdev = 0; // FIXME
}
void Pipe::on_clone(int status_flags)

View File

@@ -28,8 +28,9 @@ namespace Kernel
ProcPidInode::ProcPidInode(Process& process, TmpFileSystem& fs, const TmpInodeInfo& inode_info)
: TmpDirectoryInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info)
, m_process(process)
{
m_uid = process.credentials().ruid();
m_gid = process.credentials().rgid();
}
void ProcPidInode::cleanup()
@@ -57,7 +58,9 @@ namespace Kernel
, m_process(process)
, m_callback(callback)
{
m_inode_info.mode |= Inode::Mode::IFREG;
m_mode |= Inode::Mode::IFREG;
m_uid = process.credentials().ruid();
m_gid = process.credentials().rgid();
}
BAN::ErrorOr<size_t> ProcROProcessInode::read_impl(off_t offset, BAN::ByteSpan buffer)
@@ -82,7 +85,9 @@ namespace Kernel
, m_process(process)
, m_callback(callback)
{
m_inode_info.mode |= Inode::Mode::IFLNK;
m_mode |= Inode::Mode::IFLNK;
m_uid = process.credentials().ruid();
m_gid = process.credentials().rgid();
}
BAN::ErrorOr<BAN::String> ProcSymlinkProcessInode::link_target_impl()
@@ -104,7 +109,7 @@ namespace Kernel
: TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info)
, m_callback(callback)
{
m_inode_info.mode |= Inode::Mode::IFREG;
m_mode |= Inode::Mode::IFREG;
}
BAN::ErrorOr<size_t> ProcROInode::read_impl(off_t offset, BAN::ByteSpan buffer)
@@ -130,7 +135,7 @@ namespace Kernel
, m_destructor(destructor)
, m_data(data)
{
m_inode_info.mode |= Inode::Mode::IFLNK;
m_mode |= Inode::Mode::IFLNK;
}
ProcSymlinkInode::~ProcSymlinkInode()
@@ -158,6 +163,8 @@ namespace Kernel
: TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info)
, m_process(process)
{
m_uid = process.credentials().ruid();
m_gid = process.credentials().rgid();
ASSERT(mode().ifdir());
}

View File

@@ -131,7 +131,7 @@ namespace Kernel
PageTable::with_fast_page(inode_location.paddr, [&] {
auto& inode_info = PageTable::fast_page_as_sized<TmpInodeInfo>(inode_location.index);
ASSERT(inode_info.nlink == 0);
for (auto paddr : inode_info.block)
for (auto paddr : inode_info.tmp_blocks.block)
ASSERT(paddr == 0);
inode_info = {};
});

View File

@@ -48,11 +48,6 @@ namespace Kernel
return &m_fs;
}
dev_t TmpInode::dev() const
{
return m_fs.rdev();
}
BAN::ErrorOr<BAN::RefPtr<TmpInode>> TmpInode::create_from_existing(TmpFileSystem& fs, ino_t ino, const TmpInodeInfo& info)
{
TmpInode* inode_ptr = nullptr;
@@ -74,9 +69,21 @@ namespace Kernel
TmpInode::TmpInode(TmpFileSystem& fs, ino_t ino, const TmpInodeInfo& info)
: m_fs(fs)
, m_inode_info(info)
, m_ino(ino)
{
m_ino = ino;
m_rdev = 0;
m_blksize = PAGE_SIZE;
m_mode = info.mode;
m_nlink = info.nlink;
m_uid = info.uid;
m_gid = info.gid;
m_size = info.size;
m_atime = info.atime;
m_mtime = info.mtime;
m_ctime = info.ctime;
m_blocks = info.blocks;
m_dev = fs.rdev();
m_tmp_blocks = info.tmp_blocks;
// FIXME: this should be able to fail
MUST(fs.add_to_cache(this));
}
@@ -96,16 +103,16 @@ namespace Kernel
{
// FIXME: make this atomic
ASSERT(!(new_mode & Inode::Mode::TYPE_MASK));
m_inode_info.mode &= Inode::Mode::TYPE_MASK;
m_inode_info.mode |= new_mode;
m_mode &= Inode::Mode::TYPE_MASK;
m_mode |= new_mode;
return {};
}
BAN::ErrorOr<void> TmpInode::chown_impl(uid_t new_uid, gid_t new_gid)
{
// FIXME: make this atomic
m_inode_info.uid = new_uid;
m_inode_info.gid = new_gid;
m_uid = new_uid;
m_gid = new_gid;
return {};
}
@@ -113,33 +120,45 @@ namespace Kernel
{
// FIXME: make this atomic
if (times[0].tv_nsec != UTIME_OMIT)
m_inode_info.atime = times[0];
m_atime = times[0];
if (times[1].tv_nsec != UTIME_OMIT)
m_inode_info.atime = times[1];
m_atime = times[1];
return {};
}
void TmpInode::sync()
{
m_fs.write_inode(m_ino, m_inode_info);
TmpInodeInfo info = {
.mode = m_mode.load(),
.uid = m_uid.load(),
.gid = m_gid.load(),
.atime = m_atime,
.ctime = m_ctime,
.mtime = m_mtime,
.nlink = m_nlink.load(),
.size = static_cast<size_t>(size()),
.blocks = m_blocks.load(),
.tmp_blocks = m_tmp_blocks,
};
m_fs.write_inode(m_ino, info);
}
void TmpInode::free_all_blocks()
{
LockGuard _(m_lock);
if (mode().iflnk() && m_inode_info.size <= sizeof(TmpInodeInfo::block))
if (mode().iflnk() && static_cast<size_t>(size()) <= sizeof(TmpBlocks::block))
goto free_all_blocks_done;
for (size_t i = 0; i < TmpInodeInfo::direct_block_count; i++)
if (m_inode_info.block[i])
m_fs.free_block(m_inode_info.block[i]);
if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 0])
for (size_t i = 0; i < TmpBlocks::direct_block_count; i++)
if (m_tmp_blocks.block[i])
m_fs.free_block(m_tmp_blocks.block[i]);
if (size_t block = m_tmp_blocks.block[TmpBlocks::direct_block_count + 0])
free_indirect_blocks_no_lock(block, 1);
if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 1])
if (size_t block = m_tmp_blocks.block[TmpBlocks::direct_block_count + 1])
free_indirect_blocks_no_lock(block, 2);
if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 2])
if (size_t block = m_tmp_blocks.block[TmpBlocks::direct_block_count + 2])
free_indirect_blocks_no_lock(block, 3);
free_all_blocks_done:
for (auto& block : m_inode_info.block)
for (auto& block : m_tmp_blocks.block)
block = 0;
}
@@ -174,26 +193,26 @@ namespace Kernel
{
LockGuard _(m_lock);
if (data_block_index < TmpInodeInfo::direct_block_count)
if (data_block_index < TmpBlocks::direct_block_count)
{
if (m_inode_info.block[data_block_index] == 0)
if (m_tmp_blocks.block[data_block_index] == 0)
return {};
return m_inode_info.block[data_block_index];
return m_tmp_blocks.block[data_block_index];
}
data_block_index -= TmpInodeInfo::direct_block_count;
data_block_index -= TmpBlocks::direct_block_count;
const size_t indices_per_block = blksize() / sizeof(size_t);
if (data_block_index < indices_per_block)
return block_index_from_indirect_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 0], data_block_index, 1);
return block_index_from_indirect_no_lock(m_tmp_blocks.block[TmpBlocks::direct_block_count + 0], data_block_index, 1);
data_block_index -= indices_per_block;
if (data_block_index < indices_per_block * indices_per_block)
return block_index_from_indirect_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 1], data_block_index, 2);
return block_index_from_indirect_no_lock(m_tmp_blocks.block[TmpBlocks::direct_block_count + 1], data_block_index, 2);
data_block_index -= indices_per_block * indices_per_block;
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
return block_index_from_indirect_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 2], data_block_index, 3);
return block_index_from_indirect_no_lock(m_tmp_blocks.block[TmpBlocks::direct_block_count + 2], data_block_index, 3);
ASSERT_NOT_REACHED();
}
@@ -228,29 +247,29 @@ namespace Kernel
{
LockGuard _(m_lock);
if (data_block_index < TmpInodeInfo::direct_block_count)
if (data_block_index < TmpBlocks::direct_block_count)
{
if (m_inode_info.block[data_block_index] == 0)
if (m_tmp_blocks.block[data_block_index] == 0)
{
m_inode_info.block[data_block_index] = TRY(m_fs.allocate_block());
m_inode_info.blocks++;
m_tmp_blocks.block[data_block_index] = TRY(m_fs.allocate_block());
m_blocks++;
}
return m_inode_info.block[data_block_index];
return m_tmp_blocks.block[data_block_index];
}
data_block_index -= TmpInodeInfo::direct_block_count;
data_block_index -= TmpBlocks::direct_block_count;
const size_t indices_per_block = blksize() / sizeof(size_t);
if (data_block_index < indices_per_block)
return block_index_from_indirect_with_allocation_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 0], data_block_index, 1);
return block_index_from_indirect_with_allocation_no_lock(m_tmp_blocks.block[TmpBlocks::direct_block_count + 0], data_block_index, 1);
data_block_index -= indices_per_block;
if (data_block_index < indices_per_block * indices_per_block)
return block_index_from_indirect_with_allocation_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 1], data_block_index, 2);
return block_index_from_indirect_with_allocation_no_lock(m_tmp_blocks.block[TmpBlocks::direct_block_count + 1], data_block_index, 2);
data_block_index -= indices_per_block * indices_per_block;
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
return block_index_from_indirect_with_allocation_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 2], data_block_index, 3);
return block_index_from_indirect_with_allocation_no_lock(m_tmp_blocks.block[TmpBlocks::direct_block_count + 2], data_block_index, 3);
ASSERT_NOT_REACHED();
}
@@ -260,7 +279,7 @@ namespace Kernel
if (block == 0)
{
block = TRY(m_fs.allocate_block());
m_inode_info.blocks++;
m_blocks++;
}
ASSERT(depth >= 1);
@@ -278,7 +297,7 @@ namespace Kernel
if (next_block == 0)
{
next_block = TRY(m_fs.allocate_block());
m_inode_info.blocks++;
m_blocks++;
m_fs.with_block_buffer(block, [&](BAN::ByteSpan block_buffer) {
block_buffer.as_span<size_t>()[(index / divisor) % indices_per_block] = next_block;
@@ -385,9 +404,7 @@ namespace Kernel
{
// FIXME: if size is decreased, we should probably free
// unused blocks
// FIXME: make this atomic
m_inode_info.size = new_size;
m_size = new_size;
return {};
}
@@ -446,12 +463,12 @@ namespace Kernel
LockGuard _(m_lock);
free_all_blocks();
m_inode_info.size = 0;
m_size = 0;
if (new_target.size() <= sizeof(TmpInodeInfo::block))
if (new_target.size() <= sizeof(TmpBlocks::block))
{
memcpy(m_inode_info.block.data(), new_target.data(), new_target.size());
m_inode_info.size = new_target.size();
memcpy(m_tmp_blocks.block.data(), new_target.data(), new_target.size());
m_size = new_target.size();
return {};
}
@@ -465,7 +482,7 @@ namespace Kernel
memcpy(bytespan.data(), new_target.data() + i * blksize(), byte_count);
});
m_inode_info.size += byte_count;
m_size += byte_count;
}
return {};
@@ -478,9 +495,9 @@ namespace Kernel
BAN::String result;
TRY(result.resize(size()));
if ((size_t)size() <= sizeof(TmpInodeInfo::block))
if ((size_t)size() <= sizeof(TmpBlocks::block))
{
memcpy(result.data(), m_inode_info.block.data(), size());
memcpy(result.data(), m_tmp_blocks.block.data(), size());
return result;
}
@@ -569,14 +586,14 @@ namespace Kernel
{
auto inode = TRY(m_fs.open_inode(dot_ino));
ASSERT(inode->nlink() > 0);
inode->m_inode_info.nlink--;
inode->m_nlink--;
}
if (dotdot_ino)
{
auto inode = TRY(m_fs.open_inode(dotdot_ino));
ASSERT(inode->nlink() > 0);
inode->m_inode_info.nlink--;
inode->m_nlink--;
}
return {};
@@ -754,7 +771,7 @@ namespace Kernel
if (cleanup)
TRY(inode->prepare_unlink_no_lock());
inode->m_inode_info.nlink--;
inode->m_nlink--;
if (inode->nlink() == 0)
m_fs.remove_from_cache(inode);
@@ -837,7 +854,7 @@ namespace Kernel
if (done)
{
// add link to linked inode
inode.m_inode_info.nlink++;
inode.m_nlink++;
return {};
}
}
@@ -866,10 +883,10 @@ namespace Kernel
});
// increase current size
m_inode_info.size += blksize();
m_size += blksize();
// add link to linked inode
inode.m_inode_info.nlink++;
inode.m_nlink++;
return {};
}