예제 #1
0
/**
 * Converts all inodes in the inodes-dir (fomerly 'entries') to the new format and stores
 * into the correct dir.
 */
bool Upgrade::initInodesBackupDir(std::string storageDir)
{
   const char* logContext = "initialize the entries backup dir";
   this->inodesBackupPath = storageDir + "/" META_INODES_SUBDIR_NAME_OLD META_UPGRADE_BACKUP_EXT;

   if (!doMkDir(inodesBackupPath) )
   {
      LogContext(logContext).logErr("Failed to create inodes backup dir. Aborting!");
      return false;
   }

   // create  inode backup hash subdirs
   for(unsigned i=0; i < HASHDIRS_NUM_OLD; i++)
   {
      std::string subDirHash = StringTk::uintToHexStr(i);
      std::string subdirPath = inodesBackupPath + "/" + subDirHash;

      if (!doMkDir(subdirPath) )
      {
         LogContext(logContext).logErr("Failed to create inodes hash backup dir. Aborting!");
         return false;
      }
   }

   return true;
}
예제 #2
0
bool Upgrade::doMkDir(std::string path)
{
   const char* logContext = "mkdir";
   int mkDirRes = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO );
   if (mkDirRes)
   {
      if (errno == EEXIST)
      {
         // path exists already => check whether it is a directory
         struct stat statStruct;
         int statRes = stat(path.c_str(), &statStruct);
         if(statRes || !S_ISDIR(statStruct.st_mode) )
         {
            LogContext(logContext).logErr("mkdir path already exists, but is not a directory: " +
               path);
            return false;
         }

         return true; // already exists
      }

      LogContext(logContext).logErr("Failed to create directory: " + path + ": " +
         System::getErrString() );
      return false;
   }

   return true;
}
예제 #3
0
void MsgHelperRepair::createContDirs(Node* node, FsckDirInodeList* inodes,
   StringList* failedCreates)
{
   const char* logContext = "MsgHelperRepair (createContDirs)";

   // create a string list with the IDs
   StringList directoryIDs;
   for (FsckDirInodeListIter iter = inodes->begin(); iter != inodes->end(); iter++)
   {
      directoryIDs.push_back(iter->getID());
   }

   bool commRes;
   char *respBuf = NULL;
   NetMessage *respMsg = NULL;

   CreateEmptyContDirsMsg createContDirsMsg(&directoryIDs);

   commRes = MessagingTk::requestResponse(node, &createContDirsMsg,
      NETMSGTYPE_CreateEmptyContDirsResp, &respBuf, &respMsg);

   if ( commRes )
   {
      CreateEmptyContDirsRespMsg* createContDirsRespMsg = (CreateEmptyContDirsRespMsg*) respMsg;

      // parse failed inserts
      createContDirsRespMsg->parseFailedIDs(failedCreates);

      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);
   }
   else
   {
      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);

      *failedCreates = directoryIDs;

      LogContext(logContext).logErr(
         "Communication error occured with node: " + node->getID());
   }

   if ( !failedCreates->empty() )
   {
      for ( StringListIter iter = failedCreates->begin(); iter != failedCreates->end();
         iter++ )
      {
         LogContext(logContext).log(Log_CRITICAL, "Failed to create empty content directory. "
            "directoryID: " + *iter);
      }
   }
}
예제 #4
0
void MsgHelperRepair::deleteFiles(Node* node, FsckDirEntryList* dentries,
   FsckDirEntryList* failedDeletes)
{
   const char* logContext = "MsgHelperRepair (deleteFiles)";

   for ( FsckDirEntryListIter iter = dentries->begin(); iter != dentries->end(); iter++ )
   {
      bool commRes;
      char *respBuf = NULL;
      NetMessage *respMsg = NULL;

      EntryInfo parentInfo(node->getNumID(), "", iter->getParentDirID(), "", DirEntryType_DIRECTORY,
         0);

      std::string entryName = iter->getName();
      UnlinkFileMsg unlinkFileMsg(&parentInfo, entryName);

      commRes = MessagingTk::requestResponse(node, &unlinkFileMsg, NETMSGTYPE_UnlinkFileResp,
         &respBuf, &respMsg);

      if ( commRes )
      {
         UnlinkFileRespMsg* unlinkFileRespMsg = (UnlinkFileRespMsg*) respMsg;

         // get result
         int unlinkRes = unlinkFileRespMsg->getValue();

         if ( unlinkRes )
         {
            LogContext(logContext).log(Log_CRITICAL,
               "Failed to delete file; entryID: " + iter->getID());
            failedDeletes->push_back(*iter);
         }

         SAFE_FREE(respBuf);
         SAFE_DELETE(respMsg);
      }
      else
      {
         SAFE_FREE(respBuf);
         SAFE_DELETE(respMsg);

         failedDeletes->push_back(*iter);

         LogContext(logContext).logErr("Communication error occured with node: " + node->getID());
      }

   }
}
예제 #5
0
void MsgHelperRepair::linkToLostAndFound(Node* lostAndFoundNode, EntryInfo* lostAndFoundInfo,
   FsckFileInodeList* fileInodes, FsckFileInodeList* failedInodes,
   FsckDirEntryList* createdDentries)
{
   const char* logContext = "MsgHelperRepair (linkToLostAndFound)";

   bool commRes;
   char *respBuf = NULL;
   NetMessage *respMsg = NULL;

   LinkToLostAndFoundMsg linkToLostAndFoundMsg(lostAndFoundInfo, fileInodes);

   commRes = MessagingTk::requestResponse(lostAndFoundNode, &linkToLostAndFoundMsg,
      NETMSGTYPE_LinkToLostAndFoundResp, &respBuf, &respMsg);

   if ( commRes )
   {
      LinkToLostAndFoundRespMsg* linkToLostAndFoundRespMsg = (LinkToLostAndFoundRespMsg*) respMsg;

      // parse failed inserts
      linkToLostAndFoundRespMsg->parseFailedInodes(failedInodes);

      // parse created dentries
      linkToLostAndFoundRespMsg->parseCreatedDirEntries(createdDentries);

      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);
   }
   else
   {
      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);

      *failedInodes = *fileInodes;

      LogContext(logContext).logErr("Communication error occured with node: " +
         lostAndFoundNode->getID());
   }

   if (! failedInodes->empty())
   {
      for (FsckFileInodeListIter iter = failedInodes->begin(); iter != failedInodes->end();
         iter++)
      {
         LogContext(logContext).log(Log_CRITICAL, "Failed to link file inode to lost+found. "
            "entryID: " + iter->getID());
      }
   }
}
예제 #6
0
void MsgHelperRepair::createDefDirInodes(Node* node, StringList* inodeIDs,
   FsckDirInodeList* createdInodes)
{
   const char* logContext = "MsgHelperRepair (createDefDirInodes)";

   StringList failedInodeIDs;

   bool commRes;
   char *respBuf = NULL;
   NetMessage *respMsg = NULL;

   CreateDefDirInodesMsg createDefDirInodesMsgEx(inodeIDs);

   commRes = MessagingTk::requestResponse(node, &createDefDirInodesMsgEx,
      NETMSGTYPE_CreateDefDirInodesResp, &respBuf, &respMsg);

   if ( commRes )
   {
      CreateDefDirInodesRespMsg* createDefDirInodesRespMsg = (CreateDefDirInodesRespMsg*) respMsg;

      // parse failed creates
      createDefDirInodesRespMsg->parseFailedInodeIDs(&failedInodeIDs);

      // parse created inodes
      createDefDirInodesRespMsg->parseCreatedInodes(createdInodes);

      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);
   }
   else
   {
      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);

      failedInodeIDs = *inodeIDs;

      LogContext(logContext).logErr("Communication error occured with node: " + node->getID());
   }

   if (! failedInodeIDs.empty())
   {
      for (StringListIter iter = failedInodeIDs.begin(); iter != failedInodeIDs.end(); iter++)
      {
         LogContext(logContext).log(Log_CRITICAL, "Failed to create default directory inode on "
            "metadata node: " + node->getID() + " entryID: " + *iter);
      }
   }
}
예제 #7
0
FhgfsOpsErr MirrorMetadataWork::communicate()
{
   const char* logContext = "Mirror metadata work";

   App* app = Program::getApp();
   FhgfsOpsErr remoteRes;

   // prepare request

   MirrorMetadataMsgEx mirrorMsg(taskList, taskListNumElems, taskListSerialLen);

   RequestResponseArgs rrArgs(NULL, &mirrorMsg, NETMSGTYPE_MirrorMetadataResp);

   RequestResponseNode rrNode(nodeID, app->getMetaNodes() );
   rrNode.setTargetStates(app->getMetaStateStore() );

   // send request to node and receive response

   FhgfsOpsErr requestRes = MessagingTk::requestResponseNode(&rrNode, &rrArgs);

   if(unlikely(requestRes != FhgfsOpsErr_SUCCESS) )
   { // communication error
      LogContext(logContext).log(Log_WARNING,
         "Communication with metadata server failed. "
         "nodeID: " + StringTk::uintToStr(nodeID) );
      return requestRes;
   }

   // correct response type received
   MirrorMetadataRespMsg* mirrorRespMsg = (MirrorMetadataRespMsg*)rrArgs.outRespMsg;

   remoteRes = mirrorRespMsg->getResult();
   if(unlikely(remoteRes != FhgfsOpsErr_SUCCESS) )
   { // server returned an error
      LogContext(logContext).log(Log_WARNING,
         "Metadata mirroring failed on server: " + StringTk::uintToStr(nodeID) + "; "
         "Error: " + FhgfsOpsErrTk::toErrString(remoteRes) + "; "
         "NumTasks: " + StringTk::uintToStr(taskList->size() ) );
   }
   else
   { // mirroring successful
      LOG_DEBUG(logContext, Log_DEBUG,
         "Metadata mirroring successful on server: " + StringTk::uintToStr(nodeID) + "; "
         "NumTasks: " + StringTk::uintToStr(taskList->size() ) );
   }

   return remoteRes;
}
예제 #8
0
LogContext AllocStack::log() const {
	if (_logs.empty()) {
		return LogContext(top());
	} else {
		return _logs.get();
	}
}
예제 #9
0
void InodeFileStore::clearStoreUnlocked()
{
   const char* logContext = "FileStore::clearStoreUnlocked";
   App* app = Program::getApp();

   LOG_DEBUG(logContext, Log_DEBUG,
      std::string("# of loaded entries to be cleared: ") + StringTk::intToStr(inodes.size() ) );
   IGNORE_UNUSED_VARIABLE(logContext);

   for(InodeMapIter iter = inodes.begin(); iter != inodes.end(); iter++)
   {
      FileInode* file = iter->second->getReferencedObject();

      if(unlikely(file->getNumSessionsAll() ) )
      { // check whether file was still open
         LOG_DEBUG(logContext, Log_DEBUG,
            std::string("File was still open during shutdown: ") +
            file->getEntryID() + "; # of sessions: " +
            StringTk::intToStr(file->getNumSessionsAll() ) );

         if (!app->getSelfTerminate() )
            LogContext(logContext).logBacktrace();
      }

      delete(iter->second);
   }

   inodes.clear();
}
예제 #10
0
/**
 * Note: This works by serializing the original and marking the object unreferencable (exclusive),
 * so remember to call movingCancel() or movingComplete()
 *
 * @param buf target buffer for serialization (only valid if success is returned)
 * @param bufLen must be at least META_SERBUF_SIZE
 * @param outUsedBufLen the used bufLen
 */
FhgfsOpsErr InodeFileStore::moveRemoteBegin(EntryInfo* entryInfo, char* buf, size_t bufLen,
   size_t* outUsedBufLen)
{
   const char* logContext = "Serialize Inode";
   FhgfsOpsErr retVal = FhgfsOpsErr_PATHNOTEXISTS;

   if(bufLen < META_SERBUF_SIZE)
   {
      LogContext(logContext).log(Log_ERR, "Error: Buffer too small!");
      return FhgfsOpsErr_INTERNAL;
   }

   SafeRWLock safeLock(&rwlock, SafeRWLock_WRITE); // L O C K

   FileInode* inode;
   retVal = getUnreferencedInodeUnlocked(entryInfo, &inode); // does not set refCount
   if (retVal == FhgfsOpsErr_SUCCESS)
   {
      /* We got an inode, which is in the map, but is unreferenced. Now we are going to exclusively
       * lock it. If another thread should try to reference it, it will fail due to this lock.
       */
      *outUsedBufLen = inode->serializeMetaData(buf);
      inode->setExclusive(true);
   }

   safeLock.unlock(); // U N L O C K

   return retVal;
}
예제 #11
0
bool MkLocalDirMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock,
   char* respBuf, size_t bufLen, HighResolutionStats* stats)
{
   const char* logContext = "MkLocalDirMsg incoming";

   EntryInfo* entryInfo = getEntryInfo();

   std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername();
   LOG_DEBUG(logContext, 4, std::string("Received a MkLocalDirMsg from: ") + peer +
      std::string(" entryID: ") + entryInfo->getEntryID() +
      std::string(" entryName: ") + entryInfo->getFileName() );

   IGNORE_UNUSED_VARIABLE(logContext);
   IGNORE_UNUSED_VARIABLE(entryInfo);

   FhgfsOpsErr mkRes = FhgfsOpsErr_INTERNAL;
   
   StripePattern* pattern = createPattern();
   if(unlikely(pattern->getPatternType() == STRIPEPATTERN_Invalid) )
      LogContext(logContext).logErr("Received an invalid stripe pattern from: " + peer);
   else
      mkRes = mkLocalDir(pattern);

   delete(pattern);

   MkLocalDirRespMsg respMsg(mkRes);
   respMsg.serialize(respBuf, bufLen);
   sock->sendto(respBuf, respMsg.getMsgLength(), 0,
      (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) );

   return true;
}
예제 #12
0
bool Upgrade::migrateInode(std::string inodeID, std::string inodePath, std::string subDirHash)
{
   const char* logContext = "migrage Inode";

   bool isDirInode;

   unsigned strLen = inodeID.length();
   std::string suffix = inodeID.substr(strLen - 2, SUFFIX_LENGTH);

   if (suffix.compare("-d") == 0 )
      isDirInode = true;
   else
   if (suffix.compare("-f") == 0)
      isDirInode = false;
   else
   {
      LogContext(logContext).logErr("");
      LogContext(logContext).logErr("Inode is neither a dir nor a directory: " + inodePath );
      this->allOK = false;
      return false;
   }

   std::string idWithOutSuffix = inodeID;
   idWithOutSuffix.resize(strLen - 2);
   bool migrateRes;

   if (isDirInode)
   {
      // Hmm, shall we really do anything here? Actually migrate migrateDentries() is a better
      // place to handle DirInodes. If there is no contents dir, this DirInode can be deleted,
      // as there are no entries...

      DirInode* inode = NULL;

      migrateRes = migrateDirInode(idWithOutSuffix, &inode);
      if (migrateRes == true)
         backupOrDeleteDirInode(inode);

      SAFE_DELETE(inode);

      return migrateRes;
   }
   else
      migrateRes = migrateFileInode(idWithOutSuffix);

   return migrateRes;
}
예제 #13
0
void MsgHelperRepair::deleteFileInodes(Node* node, FsckFileInodeList& inodes,
   StringList& failedDeletes)
{
   const char* logContext = "MsgHelperRepair (deleteFileInodes)";

   StringList entryIDList;
   DirEntryTypeList entryTypeList;

   for ( FsckFileInodeListIter iter = inodes.begin(); iter != inodes.end(); iter++ )
   {
      entryIDList.push_back(iter->getID());
      entryTypeList.push_back(DirEntryType_REGULARFILE);
   }

   bool commRes;
   char *respBuf = NULL;
   NetMessage *respMsg = NULL;

   RemoveInodesMsg removeInodesMsg(&entryIDList, &entryTypeList);

   commRes = MessagingTk::requestResponse(node, &removeInodesMsg,
      NETMSGTYPE_RemoveInodesResp, &respBuf, &respMsg);

   if ( commRes )
   {
      RemoveInodesRespMsg* removeInodesRespMsg = (RemoveInodesRespMsg*) respMsg;
      removeInodesRespMsg->parseFailedEntryIDList(&failedDeletes);

      for ( StringListIter iter = failedDeletes.begin(); iter != failedDeletes.end();
         iter++ )
      {
         LogContext(logContext).logErr(
            "Failed to delete file inode; nodeID: " + StringTk::uintToStr(node->getNumID())
               + "; entryID: " + *iter);
      }

   }
   else
   {
      LogContext(logContext).logErr("Communication error occured with node: " + node->getID());

      failedDeletes = entryIDList;
   }

   SAFE_FREE(respBuf);
   SAFE_DELETE(respMsg);
}
예제 #14
0
void MsgHelperRepair::recreateDentries(Node* node, FsckFsIDList* fsIDs, FsckFsIDList* failedCreates,
   FsckDirEntryList* createdDentries, FsckFileInodeList* createdInodes)
{
   const char* logContext = "MsgHelperRepair (recreateDentries)";

   bool commRes;
   char *respBuf = NULL;
   NetMessage *respMsg = NULL;

   RecreateDentriesMsg recreateDentriesMsg(fsIDs);

   commRes = MessagingTk::requestResponse(node, &recreateDentriesMsg,
      NETMSGTYPE_RecreateDentriesResp, &respBuf, &respMsg);

   if ( commRes )
   {
      RecreateDentriesRespMsg* recreateDentriesMsg = (RecreateDentriesRespMsg*) respMsg;

      // parse failed creates
      recreateDentriesMsg->parseFailedCreates(failedCreates);
      recreateDentriesMsg->parseCreatedDentries(createdDentries);
      recreateDentriesMsg->parseCreatedInodes(createdInodes);

      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);
   }
   else
   {
      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);

      *failedCreates = *fsIDs;

      LogContext(logContext).logErr("Communication error occured with node: " + node->getID());
   }

   if ( !failedCreates->empty() )
   {
      for ( FsckFsIDListIter iter = failedCreates->begin(); iter != failedCreates->end();
         iter++ )
      {
         LogContext(logContext).log(Log_CRITICAL, "Failed to recreate dentry."
            " entryID: " + iter->getID());
      }
   }
}
예제 #15
0
void InternodeSyncer::updateTargetBuddyCapacityPools()
{
   App* app = Program::getApp();

   MirrorBuddyGroupMapper* buddyMapper = app->getMirrorBuddyGroupMapper();
   TargetCapacityPools* targetPools = app->getStorageCapacityPools();
   NodeCapacityPools* buddyPools = app->getStorageBuddyCapacityPools();

   UInt16Set listNormal; // new "normal" buddy group pool list
   UInt16Set listLow;
   UInt16Set listEmergency;

   UInt16List buddyGroupIDs;
   MirrorBuddyGroupList buddyGroups;

   buddyMapper->getMappingAsLists(buddyGroupIDs, buddyGroups);

   UInt16ListConstIter buddyGroupIDIter = buddyGroupIDs.begin();
   MirrorBuddyGroupListCIter buddyGroupIter = buddyGroups.begin();

   // walk all mapped buddy groups, add them to buddy pools based on worst buddy pool of any buddy
   for( ; buddyGroupIDIter != buddyGroupIDs.end(); buddyGroupIDIter++, buddyGroupIter++)
   {
      CapacityPoolType primaryPoolType;
      bool primaryFound = targetPools->getPoolAssignment(buddyGroupIter->firstTargetID,
         &primaryPoolType);

      if(!primaryFound)
         continue; // can't make a pool decision if a buddy does not exist

      CapacityPoolType secondaryPoolType;
      bool secondaryFound = targetPools->getPoolAssignment(buddyGroupIter->secondTargetID,
         &secondaryPoolType);

      if(!secondaryFound)
         continue; // can't make a pool decision if a buddy does not exist

      CapacityPoolType groupPoolType = BEEGFS_MAX(primaryPoolType, secondaryPoolType);

      if(groupPoolType == CapacityPool_NORMAL)
         listNormal.insert(*buddyGroupIDIter);
      else
      if(groupPoolType == CapacityPool_LOW)
         listLow.insert(*buddyGroupIDIter);
      else
      if(groupPoolType == CapacityPool_EMERGENCY)
         listEmergency.insert(*buddyGroupIDIter);
      else
      { // should never happen
         LogContext(__func__).logErr(
            "Skipping invalid groupPoolType: " + StringTk::intToStr(groupPoolType) );
      }
   }

   // apply new pools

   buddyPools->syncPoolsFromSets(listNormal, listLow, listEmergency);
}
예제 #16
0
/**
 * Get the difference vector of op counters between previous and current values
 * NOTE: The result MUST be free'ed from the caller.
 */
UInt64Vector* ClientStatsDiff::newDiffVector(uint64_t IP)
{
   LogContext log = LogContext("ClientStatsDiff ( new diff vector)");

   UInt64Vector* currentVec = ClientStats::getVectorFromMap(this->currentVecMap, IP);

   if (!currentVec)
   {
      struct in_addr in_addr = { (in_addr_t)IP };
      std::string logMessage("BUG: Missing vector for IP" + Socket::ipaddrToStr(&in_addr) );

      log.logErr(logMessage);
      std::cerr << logMessage << std::endl;
      return NULL;
   }

   UInt64Vector* diffVec = new UInt64Vector(*currentVec); // copy of the current values first

   UInt64Vector* oldVec     = ClientStats::getVectorFromMap(this->oldVecMap, IP);
   if (!oldVec)
      return diffVec; // IP just did not do any IO last time, so old values are zero


   uint64_t oldIP = oldVec->at(OPCOUNTERVECTOR_POS_IP);
   uint64_t curIP = currentVec->at(OPCOUNTERVECTOR_POS_IP);
   if (oldIP != curIP)
   {
      struct in_addr cur_addr = { (in_addr_t)curIP };
      struct in_addr old_addr = { (in_addr_t)oldIP };
      std::string logMessage("Bug: IP mismatch between old and current vector " +
         Socket::ipaddrToStr(&old_addr) + "vs. " + Socket::ipaddrToStr(&cur_addr) );

      log.logErr(logMessage);
      std::cerr << logMessage << std::endl;
      return NULL;
   }

   /* vector length might be different, for example after an update to a different FhGFS version
    * on a server. So we need to check for it and to unify vector length.
    */
   int maxVecSize = BEEGFS_MAX(currentVec->size(), oldVec->size() );
   currentVec->resize(maxVecSize, 0);
   oldVec->resize(maxVecSize, 0);

   // set iter to first counter
   UInt64VectorIter diffIter =  diffVec->begin() + OPCOUNTERVECTOR_POS_FIRSTCOUNTER;
   UInt64VectorIter oldIter  =  oldVec->begin() + OPCOUNTERVECTOR_POS_FIRSTCOUNTER;

   do
   {
      // no checks required here, as we already checked the vector sizes above
      *diffIter -= *oldIter;
      oldIter++;
      diffIter++;
   } while (oldIter != oldVec->end() );

   return diffVec;
}
예제 #17
0
void MsgHelperRepair::correctInodeOwnersInDentry(Node* node, FsckDirEntryList* dentries,
   FsckDirEntryList* failedCorrections)
{
   const char* logContext = "MsgHelperRepair (correctInodeOwnersInDentry)";

   bool commRes;
   char *respBuf = NULL;
   NetMessage *respMsg = NULL;

   FixInodeOwnersInDentryMsg fixInodeOwnersMsg(dentries);

   commRes = MessagingTk::requestResponse(node, &fixInodeOwnersMsg,
      NETMSGTYPE_FixInodeOwnersInDentryResp, &respBuf, &respMsg);

   if ( commRes )
   {
      FixInodeOwnersInDentryRespMsg* fixInodeOwnersRespMsg =
         (FixInodeOwnersInDentryRespMsg*) respMsg;

      // parse failed corrections
      fixInodeOwnersRespMsg->parseFailedEntries(failedCorrections);

      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);
   }
   else
   {
      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);

      *failedCorrections = *dentries;

      LogContext(logContext).logErr("Communication error occured with node: " + node->getID());
   }

   if (! failedCorrections->empty())
   {
      for (FsckDirEntryListIter iter = failedCorrections->begin(); iter != failedCorrections->end();
         iter++)
      {
         LogContext(logContext).log(Log_CRITICAL, "Failed to correct inode owner information in "
            "dentry on on metadata node: " + node->getID() + " entryID: " + iter->getID());
      }
   }
}
예제 #18
0
void MsgHelperRepair::changeStripeTarget(Node* node, FsckFileInodeList* inodes, uint16_t targetID,
   uint16_t newTargetID, FsckFileInodeList* failedInodes)
{
   const char* logContext = "MsgHelperRepair (changeStripeTarget)";

   bool commRes;
   char *respBuf = NULL;
   NetMessage *respMsg = NULL;

   ChangeStripeTargetMsg changeStripeTargetMsg(inodes, targetID, newTargetID);

   commRes = MessagingTk::requestResponse(node, &changeStripeTargetMsg,
      NETMSGTYPE_ChangeStripeTargetResp, &respBuf, &respMsg);

   if ( commRes )
   {
      ChangeStripeTargetRespMsg* changeStripeTargetRespMsg = (ChangeStripeTargetRespMsg*) respMsg;

      // parse failed update
      changeStripeTargetRespMsg->parseFailedInodes(failedInodes);

      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);
   }
   else
   {
      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);

      *failedInodes = *inodes;

      LogContext(logContext).logErr("Communication error occured with node: " + node->getID());
   }

   if ( !failedInodes->empty() )
   {
      for ( FsckFileInodeListIter iter = failedInodes->begin(); iter != failedInodes->end();
         iter++ )
      {
         LogContext(logContext).log(Log_CRITICAL, "Failed to change stripe pattern of inode."
            " entryID: " + iter->getID());
      }
   }
}
예제 #19
0
void MsgHelperRepair::updateDirAttribs(Node* node, FsckDirInodeList* inodes,
   FsckDirInodeList* failedUpdates)
{
   const char* logContext = "MsgHelperRepair (updateDirAttribs)";

   bool commRes;
   char *respBuf = NULL;
   NetMessage *respMsg = NULL;

   UpdateDirAttribsMsg updateDirAttribsMsg(inodes);

   commRes = MessagingTk::requestResponse(node, &updateDirAttribsMsg,
      NETMSGTYPE_UpdateDirAttribsResp, &respBuf, &respMsg);

   if ( commRes )
   {
      UpdateDirAttribsRespMsg* updateDirAttribsRespMsg = (UpdateDirAttribsRespMsg*) respMsg;

      // parse failed update
      updateDirAttribsRespMsg->parseFailedInodes(failedUpdates);

      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);
   }
   else
   {
      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);

      *failedUpdates = *inodes;

      LogContext(logContext).logErr("Communication error occured with node: " + node->getID());
   }

   if ( !failedUpdates->empty() )
   {
      for ( FsckDirInodeListIter iter = failedUpdates->begin(); iter != failedUpdates->end();
         iter++ )
      {
         LogContext(logContext).log(Log_CRITICAL, "Failed to update attributes of directory inode."
            " entryID: " + iter->getID());
      }
   }
}
예제 #20
0
void MsgHelperRepair::deleteDanglingDirEntries(Node *node, FsckDirEntryList* dentries,
   FsckDirEntryList* failedDeletes)
{
   const char* logContext = "MsgHelperRepair (deleteDanglingDirEntries)";

   bool commRes;
   char *respBuf = NULL;
   NetMessage *respMsg = NULL;

   DeleteDirEntriesMsg deleteDirEntriesMsg(dentries);

   commRes = MessagingTk::requestResponse(node, &deleteDirEntriesMsg,
      NETMSGTYPE_DeleteDirEntriesResp, &respBuf, &respMsg);

   if ( commRes )
   {
      DeleteDirEntriesRespMsg* deleteDirEntriesRespMsg = (DeleteDirEntriesRespMsg*) respMsg;

      // parse failed directory entries
      deleteDirEntriesRespMsg->parseFailedEntries(failedDeletes);

      if (! failedDeletes->empty())
      {
         for (FsckDirEntryListIter iter = failedDeletes->begin(); iter != failedDeletes->end();
            iter++)
         {
            LogContext(logContext).log(Log_CRITICAL, "Failed to delete directory entry from "
               "metadata node: " + node->getID() + " entryID: " + iter->getID());
         }
      }

      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);
   }
   else
   {
      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);

      *failedDeletes = *dentries;

      LogContext(logContext).logErr("Communication error occured with node: " + node->getID());
   }
}
예제 #21
0
void MsgHelperRepair::deleteChunks(Node* node, FsckChunkList* chunks, FsckChunkList* failedDeletes)
{
   const char* logContext = "MsgHelperRepair (deleteChunks)";

   bool commRes;
   char *respBuf = NULL;
   NetMessage *respMsg = NULL;

   DeleteChunksMsg deleteChunksMsg(chunks);

   commRes = MessagingTk::requestResponse(node, &deleteChunksMsg,
      NETMSGTYPE_DeleteChunksResp, &respBuf, &respMsg);

   if ( commRes )
   {
      DeleteChunksRespMsg* deleteChunksRespMsg = (DeleteChunksRespMsg*) respMsg;

      // parse failed deletes
      deleteChunksRespMsg->parseFailedChunks(failedDeletes);

      if (! failedDeletes->empty())
      {
         for (FsckChunkListIter iter = failedDeletes->begin(); iter != failedDeletes->end();
            iter++)
         {
            LogContext(logContext).log(Log_CRITICAL, "Failed to delete chunk entry. targetID: " +
               StringTk::uintToStr(iter->getTargetID()) + " chunkID: " + iter->getID());
         }
      }

      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);
   }
   else
   {
      SAFE_FREE(respBuf);
      SAFE_DELETE(respMsg);

      *failedDeletes = *chunks;

      LogContext(logContext).logErr("Communication error occured with node: " + node->getID());
   }
}
예제 #22
0
/**
 * Reads the contents of an inode file (file or dir inode) directly from disk
 *
 * Note: Don't call this directly, use the wrapper loadInodeFromFile().
 * Note: No locking at all
 * Note: currently unused
 *
 * @param metaFilename the complete path to the inode file
 * @param outFileInode the inode contents (must be deleted by the caller), or NULL if inode is not
 * a file inode
 * @param outDirInode the inode contents (must be deleted by the caller), or NULL if inode is not
 * a dir inode
 * @return the entry type of the inode or DirEntryType_INVALID if an error occured
 */
DirEntryType StorageTkEx::readInodeFromFileContentsUnlocked(std::string& metaFilename,
   FileInode** outFileInode, DirInode** outDirInode)
{
   const char* logContext = "MetaStore (load from file contents)";

   DirEntryType retVal = DirEntryType_INVALID;

   int openFlags = O_NOATIME | O_RDONLY;

   int fd = open(metaFilename.c_str(), openFlags, 0);
   if(fd == -1)
   { // open failed
      if(errno != ENOENT)
         LogContext(logContext).logErr("Unable to open inode file: " + metaFilename + ". " +
            "SysErr: " + System::getErrString() );

      return DirEntryType_INVALID;
   }

   char* buf = (char*)malloc(META_SERBUF_SIZE);
   int readRes = read(fd, buf, META_SERBUF_SIZE);

   if(readRes <= 0)
   { // reading failed
      LogContext(logContext).logErr("Unable to read inode file: " + metaFilename + ". " +
         "SysErr: " + System::getErrString() );
   }
   else
   {
      retVal = DiskMetaData::deserializeInode(buf, outFileInode, outDirInode);
      if (unlikely(retVal == DirEntryType_INVALID))
      { // deserialization failed
         LogContext(logContext).logErr("Unable to deserialize inode in file: " + metaFilename);
      }
   }

   free(buf);
   close(fd);

   return retVal;
}
예제 #23
0
bool Upgrade::loadIDMap(std::string mapFileName, StringUnsignedMap* outIdMap)
{
   const char* logContext = "Load IP map file";

   std::ifstream fis(mapFileName.c_str() );
   if(!fis.is_open() || fis.fail() )
   {
      LogContext(logContext).logErr("Failed to open ID-map-file: " + System::getErrString() );

      return false;
   }

   bool retVal = true;
   char line[STORAGETK_FILE_MAX_LINE_LENGTH];
   while(!fis.eof() && !fis.fail() )
   {
      fis.getline(line, STORAGETK_FILE_MAX_LINE_LENGTH);
      std::string trimmedLine = StringTk::trim(line);

      if(trimmedLine.length() && (trimmedLine[0] != STORAGETK_FILE_COMMENT_CHAR) )
      {
         unsigned numID;
         char stringID[513];

         int scanRes = sscanf(trimmedLine.c_str(), "%48s %u", stringID, &numID);
         if (scanRes == ID_MAP_FILE_COLUMS)
            outIdMap->insert(StringUnsignedMapVal(stringID, numID) );
         else
         {
            LogContext(logContext).logErr("Invalid line in map file (" + mapFileName + ")" +
               std::string(" Line: ") + line);
            break;
            retVal = false;
         }
      }
   }

   fis.close();

   return retVal;
}
bool AdjustChunkPermissionsMsgEx::sendSetAttrMsg(std::string& entryID, unsigned userID,
   unsigned groupID, PathInfo* pathInfo, StripePattern* pattern)
{
   const char* logContext = "AdjustChunkPermissionsMsgEx::sendSetAttrMsg";

   MultiWorkQueue* slaveQueue = Program::getApp()->getCommSlaveQueue();

   int validAttribs = SETATTR_CHANGE_USERID | SETATTR_CHANGE_GROUPID; // only interested in these
   SettableFileAttribs attribs;
   attribs.userID = userID;
   attribs.groupID = groupID;

   const UInt16Vector* stripeTargets = pattern->getStripeTargetIDs();
   size_t numTargetWorks = stripeTargets->size();

   FhgfsOpsErrVec nodeResults(numTargetWorks);
   SynchronizedCounter counter;

   // generate work for storage targets...

   for(size_t i=0; i < numTargetWorks; i++)
   {
      SetChunkFileAttribsWork* work = new SetChunkFileAttribsWork(
         entryID, validAttribs, &attribs, false, pattern, (*stripeTargets)[i], pathInfo, NULL,
         &(nodeResults[i]), &counter);

      work->setQuotaChown(true);
      work->setMsgUserID(getMsgHeaderUserID() );

      slaveQueue->addDirectWork(work);
   }

   // wait for work completion...

   counter.waitForCount(numTargetWorks);

   // check target results...

   for(size_t i=0; i < numTargetWorks; i++)
   {
      if(unlikely(nodeResults[i] != FhgfsOpsErr_SUCCESS) )
      {
         LogContext(logContext).log(Log_WARNING,
            "Problems occurred during setting of chunk file attribs. "
            "fileID: " + entryID );

         return false;
      }
   }


   return true;
}
예제 #25
0
/**
 * Reads the contents of an inode file (file or dir inode) directly from disk
 *
 * Note: Don't call this directly, use the wrapper loadInodeFromFile().
 * Note: No locking at all
 * Note: currently unused
 *
 * @param metaFilename the complete path to the inode file
 * @param outFileInode the inode contents (must be deleted by the caller), or NULL if inode is not
 * a file inode
 * @param outDirInode the inode contents (must be deleted by the caller), or NULL if inode is not
 * a dir inode
 * @return the entry type of the inode or DirEntryType_INVALID if an error occured
 */
DirEntryType StorageTkEx::readInodeFromFileXAttrUnlocked(std::string& metaFilename,
   FileInode** outFileInode, DirInode** outDirInode)
{
   const char* logContext = "MetaStore (load from xattr file)";

   DirEntryType retVal = DirEntryType_INVALID;

   char *buf = (char*) malloc(META_SERBUF_SIZE);

   ssize_t getRes = getxattr(metaFilename.c_str(), META_XATTR_FILE_NAME, buf, META_SERBUF_SIZE);

   if ( getRes > 0 )
   { // we got something => deserialize it
      retVal = DiskMetaData::deserializeInode(buf, outFileInode, outDirInode);

      if ( unlikely(retVal == DirEntryType_INVALID) )
      { // deserialization failed
         LogContext(logContext).logErr("Unable to deserialize metadata in file: " + metaFilename);
         goto error_freebuf;
      }
   }
   else
   if ( (getRes == -1) && (errno == ENOENT) )
   { // file does not exist
      LOG_DEBUG_CONTEXT(LogContext(logContext), Log_DEBUG,
         "Inode file does not exist: " + metaFilename + ". " + "SysErr: " + System::getErrString());
   }
   else
   { // unhandled error
      LogContext(logContext).logErr(
         "Unable to open/read inode file: " + metaFilename + ". " + "SysErr: "
            + System::getErrString());
   }

   error_freebuf:
   free(buf);

   return retVal;
}
예제 #26
0
/**
 * Delete the inode on disk or move it into the backup dir.
 *
 */
bool Upgrade::backupOrDeleteDirInode(DirInode* inode)
{
   App* app = Program::getApp();
   bool deleteOldEntries = app->getConfig()->getDeleteOldFiles();
   bool retVal = true;

   if (deleteOldEntries)
   {
      const char* logContext = "Delete DirInode";

      int unlinkRes = unlink(inode->getPathToDirInode() );
      if (unlinkRes)
      {
         retVal = false;
         this->allOK = false;
         LogContext(logContext).logErr("");
         LogContext(logContext).logErr(std::string("Failed to delete old DirInode: ") +
            inode->getPathToDirInode() + std::string(" :") + System::getErrString() );
      }
   }
   else
   { // move to backup dir
      const char* logContext = "Backup DirInode";

      std::string inodeBackupDir = this->inodesBackupPath + inode->getOldHashDirPath();
      int renameRes = rename(inode->getPathToDirInode(), inodeBackupDir.c_str() );
      if (renameRes && errno != EEXIST)
      {
         retVal = false;
         this->allOK = false;
         LogContext(logContext).logErr("");
         LogContext(logContext).logErr(std::string("Failed to rename DirInode to backup dir: ") +
            inode->getPathToDirInode()  + std::string(": ") + System::getErrString() );
      }
   }

   return retVal;
}
예제 #27
0
/**
 * Wrapper for pools->addOrUpdate (metadata node version) which also produces a log message.
 * @param nodeIDStr node ID as a string for logging
 * @param reason reason the target has been put into that pool (for logging)
 * @returns true if the target has been assigned to the pool, false if it already was in that pool.
 */
bool InternodeSyncer::assignNodeToPool(NodeCapacityPools* pools, uint16_t nodeID,
   CapacityPoolType pool, const std::string& reason)
{
   const char* logContext = "Assign node to capacity pool";

   bool updateRes = pools->addOrUpdate(nodeID, pool);
   if(updateRes)
      LogContext(logContext).log(Log_WARNING, "Metadata node capacity pool assignment updated. "
         "NodeID: " + StringTk::uintToStr(nodeID) + "; "
         "Pool: " + NodeCapacityPools::poolTypeToStr(pool) + "; "
         "Reason: " + reason);

   return updateRes;
}
예제 #28
0
/**
 * Get the vector that has the statistics from the server.
 *
 * @param requestPerUserStats true to request per-user statistics instead of default per-client
 * statistics.
 */
bool ClientStatsHelper::getIOVec(Node* node, uint64_t cookieIP, bool requestPerUserStats,
   UInt64Vector* outVec)
{
   LogContext log = LogContext("ClientStats (get IO vector) ");
   bool retVal = false;

   bool commRes;
   char* respBuf = NULL;
   NetMessage* respMsg = NULL;
   GetClientStatsRespMsg* respMsgCast;
   bool parseRes;

   // we start to request a message for cookieIP=0, so no cookie set
   GetClientStatsMsg getStatsMsg(cookieIP);

   if(requestPerUserStats)
      getStatsMsg.addMsgHeaderFeatureFlag(GETCLIENTSTATSMSG_FLAG_PERUSERSTATS);

   // request/response
   commRes = MessagingTk::requestResponse(
      node, &getStatsMsg, NETMSGTYPE_GetClientStatsResp, &respBuf, &respMsg);
   if(!commRes)
   {
      std::string logMessage("Communication with node failed: " + node->getNodeIDWithTypeStr() );

      log.logErr(logMessage);
      std::cerr << logMessage << std::endl;
      goto err_cleanup;
   }

   respMsgCast = ((GetClientStatsRespMsg*)respMsg);
   parseRes = respMsgCast->parseStatsVector(outVec); // data copied into vec, so we may free respMsg
   if (!parseRes)
   {
      std::string logMessage("Parsing data from server failed: " + node->getNodeIDWithTypeStr() );

      log.logErr(logMessage);
      std::cerr << logMessage << std::endl;
      retVal = false;
      goto err_cleanup;
   }

   retVal = true;

err_cleanup:
   SAFE_DELETE(respMsg);
   SAFE_FREE(respBuf);

   return retVal;
}
예제 #29
0
/**
 * Note: remember to call releaseNode()
 *
 * @return NULL if no such node exists
 */
Node* NodeStoreServers::referenceNode(uint16_t id)
{
   // check for invalid id 0
   #ifdef FHGFS_DEBUG
   if(!id)
      LogContext(__func__).log(Log_CRITICAL, "BUG?: Attempt to reference numeric node ID '0'");
   #endif // FHGFS_DEBUG

   SafeMutexLock mutexLock(&mutex); // L O C K

   Node* node = NULL;

   if(localNode && (id == localNode->getNumID() ) )
      node = localNode;
   else
   { // search in active nodes map

      NodeMapIter iter = activeNodes.find(id);
      if(iter != activeNodes.end() )
      { // found it
         NodeReferencer* nodeRefer = iter->second;
         node = nodeRefer->reference();

         // check for unusually high reference count
         #ifdef FHGFS_DEBUG
         if(nodeRefer->getRefCount() > 100)
            LogContext(__func__).log(Log_CRITICAL,
               std::string("WARNING: Lots of references to node (=> leak?): ") +
               node->getID() + " ref count: " + StringTk::intToStr(nodeRefer->getRefCount() ) );
         #endif // FHGFS_DEBUG
      }
   }

   mutexLock.unlock(); // U N L O C K

   return node;
}
예제 #30
0
/**
 * Wrapper for pools->addOrUpdate (storage target ID version) which also produces a log message.
 * @param nodeIDStr node ID as a string for logging
 * @param reason reason the target has been put into that pool (for logging)
 * @returns true if the target has been assigned to the pool, false if it already was in that pool.
 */
bool InternodeSyncer::assignTargetToPool(TargetCapacityPools* pools, uint16_t targetID,
   uint16_t nodeID, CapacityPoolType pool, const std::string& reason)
{
   const char* logContext = "Assign target to capacity pool";

   bool updateRes = pools->addOrUpdate(targetID, nodeID, pool);
   if(updateRes)
      LogContext(logContext).log(Log_WARNING, "Storage target capacity pool assignment updated. "
         "NodeID: " + StringTk::uintToStr(nodeID) + "; "
         "TargetID: " + StringTk::uintToStr(targetID) + "; "
         "Pool: " + TargetCapacityPools::poolTypeToStr(pool) + "; "
         "Reason: " + reason);

   return updateRes;
}