From 783b77b14f0bea265fc11ee95daf1366ed08522e Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 21 Nov 2024 22:38:10 -0500 Subject: [PATCH] BFS: Fix handling of the last_modified index. Its values must be shifted before comparing against them. Also handle the last-modified times correctly in NodeGetLastModifiedTime. Fixes an issue noticed in #19080 which was a regression from the query refactor earlier this year. Also while at it, remove a needless lock in EntryGetName; Inode::GetName acquires this lock for us. --- src/add-ons/kernel/file_systems/bfs/Query.cpp | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/add-ons/kernel/file_systems/bfs/Query.cpp b/src/add-ons/kernel/file_systems/bfs/Query.cpp index fc21739d0b..bcbfec6c39 100644 --- a/src/add-ons/kernel/file_systems/bfs/Query.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Query.cpp @@ -27,19 +27,25 @@ struct Query::QueryPolicy { typedef ::Inode Node; struct Index : ::Index { + bool isSpecialTime; + Index(Context* context) : - ::Index(context->fVolume) + ::Index(context->fVolume), + isSpecialTime(false) { } }; struct IndexIterator : TreeIterator { off_t offset; + bool isSpecialTime; IndexIterator(BPlusTree* tree) : - TreeIterator(tree) + TreeIterator(tree), + offset(0), + isSpecialTime(false) { } }; @@ -71,7 +77,6 @@ struct Query::QueryPolicy { static ssize_t EntryGetName(Inode* inode, void* buffer, size_t bufferSize) { - RecursiveLocker locker(&inode->SmallDataLock()); status_t status = inode->GetName((char*)buffer, bufferSize); if (status != B_OK) return status; @@ -99,7 +104,17 @@ struct Query::QueryPolicy { static status_t IndexSetTo(Index& index, const char* attribute) { - return index.SetTo(attribute); + status_t status = index.SetTo(attribute); + if (status == B_OK) { + // The special time flag is set if the time values are shifted + // 64-bit values to reduce the number of duplicates. + // We have to be able to compare them against unshifted values + // later. The only index which needs this is the last_modified + // index, but we may want to open that feature for other indices, + // too one day. + index.isSpecialTime = (strcmp(attribute, "last_modified") == 0); + } + return status; } static void IndexUnset(Index& index) @@ -132,6 +147,7 @@ struct Query::QueryPolicy { if (iterator == NULL) return NULL; + iterator->isSpecialTime = index.isSpecialTime; return iterator; } @@ -145,6 +161,13 @@ struct Query::QueryPolicy { static status_t IndexIteratorFind(IndexIterator* iterator, const void* value, size_t size) { + int64 shiftedTime; + if (iterator->isSpecialTime) { + // int64 time index; convert value. + shiftedTime = *(int64*)value << INODE_TIME_SHIFT; + value = &shiftedTime; + } + return iterator->Find((const uint8*)value, size); } @@ -158,6 +181,11 @@ struct Query::QueryPolicy { if (status != B_OK) return status; + if (iterator->isSpecialTime) { + // int64 time index; convert value. + *(int64*)indexValue >>= INODE_TIME_SHIFT; + } + *_keyLength = keyLength; *_duplicate = duplicate; return B_OK; @@ -203,7 +231,7 @@ struct Query::QueryPolicy { static time_t NodeGetLastModifiedTime(Inode* inode) { - return inode->Node().LastModifiedTime(); + return bfs_inode::ToSecs(inode->Node().LastModifiedTime()); } static status_t NodeGetAttribute(NodeHolder& holder, Inode* inode,