// cf. OVS-1381: // conflicting updates of volume entries could lead to an infinite loop around // test_and_set as upon conflict detection the cached entry wasn't dropped and hence // used in all subsequent iterations. TEST_F(MetaDataStoreTest, conflicting_updates_for_volumes) { vfs::MetaDataStore mds1(std::static_pointer_cast<yt::LockedArakoon>(registry_), cluster_id_, vfs::UseCache::T); const vfs::FrontendPath path("/volume"); const vfs::Permissions perms(S_IWUSR bitor S_IRUSR); { vfs::DirectoryEntryPtr dentry(boost::make_shared<vfs::DirectoryEntry>(vfs::DirectoryEntry::Type::Volume, mds1.alloc_inode(), perms, vfs::UserId(::getuid()), vfs::GroupId(::getgid()))); mds1.add(path, dentry); } { vfs::DirectoryEntryPtr dentry(mds1.find(path)); ASSERT_TRUE(dentry != nullptr); ASSERT_EQ(perms, dentry->permissions()); } vfs::MetaDataStore mds2(std::static_pointer_cast<yt::LockedArakoon>(registry_), cluster_id_, vfs::UseCache::T); const vfs::Permissions perms2(S_IWUSR); mds2.chmod(path, perms2); { vfs::DirectoryEntryPtr dentry(mds2.find(path)); ASSERT_TRUE(dentry != nullptr); ASSERT_EQ(perms2, dentry->permissions()); } // on mds1 the entry is cached and the change is not visible! { vfs::DirectoryEntryPtr dentry(mds1.find(path)); ASSERT_TRUE(dentry != nullptr); ASSERT_EQ(perms, dentry->permissions()); } const vfs::Permissions perms3(S_IRUSR); // this used to end up in an infinite loop around test_and_set as the cached // value was used in it. mds1.chmod(path, perms3); { vfs::DirectoryEntryPtr dentry(mds1.find(path)); ASSERT_TRUE(dentry != nullptr); ASSERT_EQ(perms3, dentry->permissions()); } }
bool FileSystem::rmtree(const Path& path) { Directory* test_dir = opendir(path); if (test_dir != NULL) { auto_Object<Directory> dir(test_dir); Directory::Entry* test_dentry = dir->read(); if (test_dentry != NULL) { auto_Object<Directory::Entry> dentry(*test_dentry); do { if (dentry->is_special()) { continue; } Path dentry_path(path / dentry->get_name()); if (dentry->ISDIR()) { if (rmtree(dentry_path)) { continue; } else { return false; } } else if (unlink(dentry_path)) { continue; } else { return false; } } while (dir->read(*dentry)); return rmdir(path); } } return false; }
TEST_F(MetaDataStoreTest, uuid_conflicting_updates_for_volumes) { vfs::MetaDataStore mds1(std::static_pointer_cast<yt::LockedArakoon>(registry_), cluster_id_, vfs::UseCache::T); const vfs::DirectoryEntryPtr root_dentry(mds1.find(vfs::FrontendPath("/"))); const vfs::ObjectId parent_id(root_dentry->object_id()); const vfs::Permissions perms(S_IWUSR bitor S_IRUSR); const std::string root("volume"); vfs::DirectoryEntryPtr dentry(boost::make_shared<vfs::DirectoryEntry>(vfs::DirectoryEntry::Type::Volume, mds1.alloc_inode(), perms, vfs::UserId(::getuid()), vfs::GroupId(::getgid()))); mds1.add(parent_id, root, dentry); { vfs::DirectoryEntryPtr volume_dentry(mds1.find(dentry->object_id())); ASSERT_TRUE(volume_dentry != nullptr); ASSERT_EQ(perms, volume_dentry->permissions()); } vfs::MetaDataStore mds2(std::static_pointer_cast<yt::LockedArakoon>(registry_), cluster_id_, vfs::UseCache::T); const vfs::Permissions perms2(S_IWUSR); mds2.chmod(dentry->object_id(), perms2); { vfs::DirectoryEntryPtr volume_dentry(mds2.find(dentry->object_id())); ASSERT_TRUE(volume_dentry != nullptr); ASSERT_EQ(perms2, volume_dentry->permissions()); } { vfs::DirectoryEntryPtr volume_dentry(mds1.find(dentry->object_id())); ASSERT_TRUE(volume_dentry != nullptr); ASSERT_EQ(perms, volume_dentry->permissions()); } const vfs::Permissions perms3(S_IRUSR); mds1.chmod(dentry->object_id(), perms3); { vfs::DirectoryEntryPtr volume_dentry(mds1.find(dentry->object_id())); ASSERT_TRUE(dentry != nullptr); ASSERT_EQ(perms3, volume_dentry->permissions()); } }
TEST_F(MetaDataStoreTest, path_and_id) { vfs::MetaDataStore mds(std::static_pointer_cast<yt::LockedArakoon>(registry_), cluster_id_, vfs::UseCache::T); const vfs::FrontendPath dpath("/dir"); const vfs::Permissions pms(S_IWUSR bitor S_IRUSR); vfs::DirectoryEntryPtr dentry(boost::make_shared<vfs::DirectoryEntry>(vfs::DirectoryEntry::Type::Directory, mds.alloc_inode(), pms, vfs::UserId(::getuid()), vfs::GroupId(::getgid()))); mds.add(dpath, dentry); ASSERT_EQ(dpath, mds.find_path(dentry->object_id())); { const vfs::DirectoryEntryPtr p(mds.find(dentry->object_id())); ASSERT_TRUE(p != nullptr); ASSERT_TRUE(*dentry == *p); } const vfs::FrontendPath fpath(dpath / "file"); vfs::DirectoryEntryPtr fentry(boost::make_shared<vfs::DirectoryEntry>(vfs::DirectoryEntry::Type::File, mds.alloc_inode(), pms, vfs::UserId(::getuid()), vfs::GroupId(::getgid()))); mds.add(dentry->object_id(), fpath.filename().string(), fentry); ASSERT_EQ(fpath, mds.find_path(fentry->object_id())); { const vfs::DirectoryEntryPtr p(mds.find(fentry->object_id())); ASSERT_TRUE(p != nullptr); ASSERT_TRUE(*fentry == *p); } }
TEST_F(MetaDataStoreTest, root) { vfs::MetaDataStore mds(std::static_pointer_cast<yt::LockedArakoon>(registry_), cluster_id_, vfs::UseCache::F); const vfs::FrontendPath root("/"); vfs::DirectoryEntryPtr dentry(mds.find(root)); ASSERT_TRUE(dentry != nullptr); EXPECT_EQ(root, mds.find_path(dentry->object_id())); vfs::DirectoryEntryPtr dentry2(mds.find(dentry->object_id())); ASSERT_TRUE(dentry2 != nullptr); }
static void __init test_pointer(void) { plain(); null_pointer(); invalid_pointer(); symbol_ptr(); kernel_ptr(); struct_resource(); addr(); escaped_str(); hex_string(); mac(); ip(); uuid(); dentry(); struct_va_format(); struct_rtc_time(); struct_clk(); bitmap(); netdev_features(); flags(); }
void MetaDataStore::add_directories(const FrontendPath& path) { LOG_TRACE(path); FrontendPath p; for (const auto& s : path) { p = FrontendPath(p / s); DirectoryEntryPtr dentry(find(p)); while (true) { if (dentry == nullptr) { DirectoryEntryPtr dentry(boost::make_shared<DirectoryEntry>(DirectoryEntry::Type::Directory, alloc_inode(), default_directory_permissions, UserId(::getuid()), GroupId(::getgid()))); try { struct timespec timebuf; struct timeval tv; TODO("X42: Better use fungi::IOException here? WIP"); int rc = clock_gettime(CLOCK_REALTIME, &timebuf); if (rc != 0) { throw std::system_error(errno, std::system_category()); } add(p, dentry); tv.tv_sec = timebuf.tv_sec; tv.tv_usec = timebuf.tv_nsec / 1000; utimes(FrontendPath(p.parent_path()), tv, tv); break; } catch (FileExistsException&) { LOG_WARN(p << ": someone else created an eponymous entry at the same time"); } } else { if (dentry->type() != DirectoryEntry::Type::Directory) { LOG_ERROR(p << " already exists but is not a directory"); throw fungi::IOException("Entry is not a directory", p.string().c_str(), ENOTDIR); } break; } } } }