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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = {};
|
||||
});
|
||||
|
||||
@@ -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 {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user