@@ -15,13 +15,7 @@ namespace Kernel {
1515ErrorOr<NonnullRefPtr<FATInode>> FATInode::create (FATFS& fs, FATEntry entry, FATEntryLocation inode_metadata_location, Vector<FATLongFileNameEntry> const & lfn_entries)
1616{
1717 auto filename = TRY (compute_filename (entry, lfn_entries));
18- u32 entry_first_cluster = entry.first_cluster_low ;
19- if (fs.m_fat_version == FATVersion::FAT32)
20- entry_first_cluster |= (static_cast <u32 >(entry.first_cluster_high ) << 16 );
21- auto inode = TRY (adopt_nonnull_ref_or_enomem (new (nothrow) FATInode (fs, entry, inode_metadata_location, move (filename))));
22- MutexLocker locker (inode->m_inode_lock );
23- inode->m_cluster_list = TRY (inode->compute_cluster_list (fs, entry_first_cluster));
24- return inode;
18+ return TRY (adopt_nonnull_ref_or_enomem (new (nothrow) FATInode (fs, entry, inode_metadata_location, move (filename))));
2519}
2620
2721FATInode::FATInode (FATFS& fs, FATEntry entry, FATEntryLocation inode_metadata_location, NonnullOwnPtr<KString> filename)
@@ -33,6 +27,18 @@ FATInode::FATInode(FATFS& fs, FATEntry entry, FATEntryLocation inode_metadata_lo
3327 dbgln_if (FAT_DEBUG, " FATInode[{}]::FATInode(): Creating inode with filename \" {}\" " , identifier (), m_filename);
3428}
3529
30+ ErrorOr<RawPtr<Vector<u32 >>> FATInode::get_cluster_list ()
31+ {
32+ VERIFY (m_inode_lock.is_locked ());
33+
34+ if (m_cluster_list)
35+ return m_cluster_list.ptr ();
36+
37+ auto cluster_list = TRY (compute_cluster_list (fs (), first_cluster ()));
38+ m_cluster_list = TRY (try_make<Vector<u32 >>(move (cluster_list)));
39+ return m_cluster_list.ptr ();
40+ }
41+
3642ErrorOr<Vector<u32 >> FATInode::compute_cluster_list (FATFS& fs, u32 first_cluster)
3743{
3844 VERIFY (m_inode_lock.is_locked ());
@@ -203,7 +209,8 @@ ErrorOr<Vector<BlockBasedFileSystem::BlockIndex>> FATInode::get_block_list()
203209
204210 Vector<BlockBasedFileSystem::BlockIndex> block_list;
205211
206- for (auto cluster : m_cluster_list) {
212+ auto cluster_list = TRY (get_cluster_list ());
213+ for (auto cluster : *cluster_list) {
207214 auto span = fs ().first_block_of_cluster (cluster);
208215 for (size_t i = 0 ; i < span.number_of_sectors ; i++) {
209216 dbgln_if (FAT_DEBUG, " FATInode[{}]::get_block_list(): Appending block {} to block list" , identifier (), BlockBasedFileSystem::BlockIndex { span.start_block .value () + i });
@@ -271,7 +278,8 @@ ErrorOr<RefPtr<FATInode>> FATInode::traverse(Function<ErrorOr<bool>(RefPtr<FATIn
271278 return EINVAL;
272279 } else {
273280 auto entry_number_bytes = i * sizeof (FATEntry);
274- auto cluster = m_cluster_list[entry_number_bytes / bytes_per_cluster];
281+ auto cluster_list = TRY (get_cluster_list ());
282+ auto cluster = (*cluster_list)[entry_number_bytes / bytes_per_cluster];
275283 auto block = BlockBasedFileSystem::BlockIndex { fs ().first_block_of_cluster (cluster).start_block .value () + (entry_number_bytes % bytes_per_cluster) / fs ().m_device_block_size };
276284
277285 auto entries_per_sector = fs ().m_device_block_size / sizeof (FATEntry);
@@ -365,8 +373,9 @@ ErrorOr<void> FATInode::allocate_and_add_cluster_to_chain()
365373
366374 u32 allocated_cluster = TRY (fs ().allocate_cluster ());
367375 dbgln_if (FAT_DEBUG, " FATInode[{}]::allocate_and_add_cluster_to_chain(): allocated cluster {}" , identifier (), allocated_cluster);
376+ auto cluster_list = TRY (get_cluster_list ());
368377
369- if (m_cluster_list. is_empty () || (m_cluster_list. size () == 1 && first_cluster () <= 1 )) {
378+ if (cluster_list-> is_empty () || (cluster_list-> size () == 1 && first_cluster () <= 1 )) {
370379 // This is the first cluster in the chain, so update the inode metadata.
371380 if (fs ().m_fat_version == FATVersion::FAT32) {
372381 // Only FAT32 uses the `first_cluster_high` field.
@@ -380,27 +389,28 @@ ErrorOr<void> FATInode::allocate_and_add_cluster_to_chain()
380389 // This is not the first cluster in the chain, so we need to update the
381390 // FAT entry for the last cluster in the chain to point to the newly
382391 // allocated cluster.
383- TRY (fs ().fat_write (m_cluster_list. last (), allocated_cluster));
392+ TRY (fs ().fat_write (cluster_list-> last (), allocated_cluster));
384393 }
385394
386- m_cluster_list. append (allocated_cluster);
395+ cluster_list-> append (allocated_cluster);
387396
388397 return {};
389398}
390399
391400ErrorOr<void > FATInode::remove_last_cluster_from_chain ()
392401{
393402 VERIFY (m_inode_lock.is_locked ());
394- VERIFY (m_cluster_list.size () > 0 );
403+ auto cluster_list = TRY (get_cluster_list ());
404+ VERIFY (cluster_list->size () > 0 );
395405
396- u32 last_cluster = m_cluster_list. take_last ();
406+ u32 last_cluster = cluster_list-> take_last ();
397407
398408 dbgln_if (FAT_DEBUG, " FATInode[{}]::remove_last_cluster_from_chain(): freeing cluster {}" , identifier (), last_cluster);
399409
400410 TRY (fs ().fat_write (last_cluster, 0 ));
401411 TRY (fs ().notify_cluster_freed (last_cluster));
402412
403- if (m_cluster_list. is_empty () || (m_cluster_list. size () == 1 && first_cluster () <= 1 )) {
413+ if (cluster_list-> is_empty () || (cluster_list-> size () == 1 && first_cluster () <= 1 )) {
404414 // We have removed the last cluster in the chain, so update the inode metadata.
405415 if (fs ().m_fat_version == FATVersion::FAT32) {
406416 // Only FAT32 uses the `first_cluster_high` field.
@@ -413,7 +423,7 @@ ErrorOr<void> FATInode::remove_last_cluster_from_chain()
413423 } else {
414424 // We have removed a cluster from the chain, so update the FAT entry for
415425 // the last cluster in the chain mark it as the end of the chain.
416- last_cluster = m_cluster_list. last ();
426+ last_cluster = cluster_list-> last ();
417427 TRY (fs ().fat_write (last_cluster, fs ().end_of_chain_marker ()));
418428 }
419429
@@ -523,6 +533,7 @@ ErrorOr<size_t> FATInode::read_bytes_locked(off_t offset, size_t count, UserOrKe
523533
524534InodeMetadata FATInode::metadata () const
525535{
536+ auto cluster_count = ceil_div (static_cast <u64 >(m_entry.file_size ), fs ().m_device_block_size * fs ().m_parameter_block ->common_bpb ()->sectors_per_cluster );
526537 return {
527538 .inode = identifier (),
528539 .size = m_entry.file_size ,
@@ -535,7 +546,7 @@ InodeMetadata FATInode::metadata() const
535546 .ctime = time_from_packed_dos (m_entry.creation_date , m_entry.creation_time ),
536547 .mtime = time_from_packed_dos (m_entry.modification_date , m_entry.modification_time ),
537548 .dtime = {},
538- .block_count = m_cluster_list. size () * fs ().m_parameter_block ->common_bpb ()->sectors_per_cluster ,
549+ .block_count = cluster_count * fs ().m_parameter_block ->common_bpb ()->sectors_per_cluster ,
539550 .block_size = fs ().m_device_block_size ,
540551 .major_device = 0 ,
541552 .minor_device = 0 ,
@@ -868,6 +879,8 @@ ErrorOr<void> FATInode::resize(u64 size, Optional<u64> clear_from, Optional<u64>
868879 VERIFY (m_inode_lock.is_locked ());
869880 VERIFY (size != m_entry.file_size );
870881
882+ auto cluster_list = TRY (get_cluster_list ());
883+
871884 u64 bytes_per_cluster = fs ().m_device_block_size * fs ().m_parameter_block ->common_bpb ()->sectors_per_cluster ;
872885
873886 u64 size_rounded_up_to_bytes_per_cluster = size;
@@ -877,10 +890,10 @@ ErrorOr<void> FATInode::resize(u64 size, Optional<u64> clear_from, Optional<u64>
877890 size_rounded_up_to_bytes_per_cluster = (size + bytes_per_cluster) - (size % bytes_per_cluster);
878891
879892 if (size > m_entry.file_size ) {
880- while (m_cluster_list. size () * bytes_per_cluster < size_rounded_up_to_bytes_per_cluster)
893+ while (cluster_list-> size () * bytes_per_cluster < size_rounded_up_to_bytes_per_cluster)
881894 TRY (allocate_and_add_cluster_to_chain ());
882895 } else {
883- while (m_cluster_list. size () * bytes_per_cluster > size_rounded_up_to_bytes_per_cluster)
896+ while (cluster_list-> size () * bytes_per_cluster > size_rounded_up_to_bytes_per_cluster)
884897 TRY (remove_last_cluster_from_chain ());
885898 }
886899
0 commit comments