From 687df40108b0103f7539fafebcce63c1f8405335 Mon Sep 17 00:00:00 2001 From: Richard Marian Thomaiyar Date: Thu, 9 May 2019 00:16:53 +0530 Subject: user-mgmt: sync ipmi user & channel conf file ipmi_user.json file is stored in non-volatile memory, and it is necessary to make sure that file is properly synced to the storage device, to avoid any corruption issue related to power loss. This fix makes sure that temporary file is fully synced with storage device and then renamed, such that the file is either in old state or in new updated state. Same is also performed for channel configuration file too. Tested: 1. Verified regular ipmi user list & channel works without any issue 2. Verifid that any power loss, immediately, once the file is written doesn't corrupt the entries. Change-Id: I9ef84573947ab6f85f66530ac4a20e9eeaddf283 Signed-off-by: Richard Marian Thomaiyar --- user_channel/channel_mgmt.cpp | 28 ++++++++++++++++++++++------ user_channel/user_mgmt.cpp | 31 +++++++++++++++++++------------ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/user_channel/channel_mgmt.cpp b/user_channel/channel_mgmt.cpp index 6be7d9a..932795c 100644 --- a/user_channel/channel_mgmt.cpp +++ b/user_channel/channel_mgmt.cpp @@ -846,17 +846,33 @@ Json ChannelConfig::readJsonFile(const std::string& configFile) int ChannelConfig::writeJsonFile(const std::string& configFile, const Json& jsonData) { - std::ofstream jsonFile(configFile); - if (!jsonFile.good()) + const std::string tmpFile = configFile + "_tmp"; + int fd = open(tmpFile.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_SYNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd < 0) { - log("JSON file not found"); + log("Error in creating json file", + entry("FILE_NAME = %s", tmpFile.c_str())); + return -EIO; + } + const auto& writeData = jsonData.dump(); + if (write(fd, writeData.c_str(), writeData.size()) != + static_cast(writeData.size())) + { + close(fd); + log("Error in writing configuration file", + entry("FILE_NAME = %s", tmpFile.c_str())); return -EIO; } + close(fd); - // Write JSON to file - jsonFile << jsonData; + if (std::rename(tmpFile.c_str(), configFile.c_str()) != 0) + { + log("Error in renaming temporary data file", + entry("FILE_NAME = %s", tmpFile.c_str())); + return -EIO; + } - jsonFile.flush(); return 0; } diff --git a/user_channel/user_mgmt.cpp b/user_channel/user_mgmt.cpp index 5ca2884..89ba142 100644 --- a/user_channel/user_mgmt.cpp +++ b/user_channel/user_mgmt.cpp @@ -1087,15 +1087,6 @@ void UserAccess::writeUserData() boost::interprocess::scoped_lock userLock{*userMutex}; - static std::string tmpFile{std::string(ipmiUserDataFile) + "_tmp"}; - std::ofstream oUsrData(tmpFile, std::ios::out | std::ios::binary); - if (!oUsrData.good()) - { - log("Error in creating temporary IPMI user data file"); - throw std::ios_base::failure( - "Error in creating temporary IPMI user data file"); - } - Json jsonUsersTbl = Json::array(); // user index 0 is reserved, starts with 1 for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex) @@ -1130,9 +1121,25 @@ void UserAccess::writeUserData() jsonUsersTbl.push_back(jsonUserInfo); } - oUsrData << jsonUsersTbl; - oUsrData.flush(); - oUsrData.close(); + static std::string tmpFile{std::string(ipmiUserDataFile) + "_tmp"}; + int fd = open(tmpFile.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_SYNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd < 0) + { + log("Error in creating temporary IPMI user data file"); + throw std::ios_base::failure( + "Error in creating temporary IPMI user data file"); + } + const auto& writeStr = jsonUsersTbl.dump(); + if (write(fd, writeStr.c_str(), writeStr.size()) != + static_cast(writeStr.size())) + { + close(fd); + log("Error in writing temporary IPMI user data file"); + throw std::ios_base::failure( + "Error in writing temporary IPMI user data file"); + } + close(fd); if (std::rename(tmpFile.c_str(), ipmiUserDataFile) != 0) { -- cgit v1.2.1