Commit f573f225 authored by Sven Breuner's avatar Sven Breuner

updated to release 6.3

parent 6c92590d
......@@ -44,20 +44,22 @@ int main(int argc, char** argv)
DIR* parentDir = opendir(parentDirectory.c_str() );
if(parentDir == NULL)
{
std::cout << "Can not get directory stream of directory: " << parentDirectory << " errno: " << errno << std::endl;
std::cout << "Can not get directory stream of directory: " << parentDirectory
<< " errno: " << errno << std::endl;
exit(-1);
}
// get a fd of the parent directory
int fd = dirfd(parentDir);
if(fd == -1)
{
std::cout << "Can not get fd from directory: " << parentDirectory << " errno: " << errno << std::endl;
std::cout << "Can not get fd from directory: " << parentDirectory
<< " errno: " << errno << std::endl;
exit(-1);
}
// check if the parent directory is located on a BeeGFS, because the striping API works only on a BeeGFS
// if the ioctl is used on a other filesystem everything can happens
// check if the parent directory is located on a BeeGFS, because the striping API works only on
// BeeGFS (Results of BeeGFS ioctls on other file systems are undefined.)
bool isBeegfs = beegfs_testIsBeeGFS(fd);
if(!isBeegfs)
{
......
......@@ -30,7 +30,7 @@ int main(int argc, char** argv)
}
// check if the file is located on a BeeGFS, because the striping API works only on a BeeGFS
// if the ioctl is used on a other filesystem everything can happens
// (Results of BeeGFS ioctls on other file systems are undefined.)
bool isBeegfs = beegfs_testIsBeeGFS(fd);
if(!isBeegfs)
{
......@@ -61,7 +61,7 @@ int main(int argc, char** argv)
default:
patternType = "INVALID";
}
std::cout << "Strip pattern of file: " << file << std::endl;
std::cout << "Stripe pattern of file: " << file << std::endl;
std::cout << "+ Type: " << patternType << std::endl;
std::cout << "+ Chunksize: " << outChunkSize << " Byte" << std::endl;
std::cout << "+ Number of storage targets: " << outNumTargets << std::endl;
......@@ -77,12 +77,20 @@ int main(int argc, char** argv)
{
if(outPatternType == BEEGFS_STRIPEPATTERN_BUDDYMIRROR)
{
std::cout << " + " << outTargetInfo.targetOrGroup << " @ " << outTargetInfo.primaryTarget << " @ " << outTargetInfo.primaryNodeStrID << " [ID: "<< outTargetInfo.primaryNodeID << "]" << std::endl;
std::cout << " + " << outTargetInfo.targetOrGroup << " @ " << outTargetInfo.secondaryTarget << " @ " << outTargetInfo.secondaryNodeStrID << " [ID: "<< outTargetInfo.secondaryNodeID << "]" << std::endl;
std::cout << " + " << outTargetInfo.targetOrGroup
<< " @ " << outTargetInfo.primaryTarget
<< " @ " << outTargetInfo.primaryNodeStrID
<< " [ID: "<< outTargetInfo.primaryNodeID << "]" << std::endl;
std::cout << " + " << outTargetInfo.targetOrGroup
<< " @ " << outTargetInfo.secondaryTarget
<< " @ " << outTargetInfo.secondaryNodeStrID
<< " [ID: "<< outTargetInfo.secondaryNodeID << "]" << std::endl;
}
else
{
std::cout << " + " << outTargetInfo.targetOrGroup << " @ " << outTargetInfo.primaryNodeStrID << " [ID: "<< outTargetInfo.primaryNodeID << "]" << std::endl;
std::cout << " + " << outTargetInfo.targetOrGroup
<< " @ " << outTargetInfo.primaryNodeStrID
<< " [ID: "<< outTargetInfo.primaryNodeID << "]" << std::endl;
}
}
else
......
......@@ -72,7 +72,8 @@
#define BEEGFS_IOC_GET_STRIPETARGET_V2 _IOR( \
BEEGFS_IOCTYPE_ID, BEEGFS_IOCNUM_GET_STRIPETARGET, struct BeegfsIoctl_GetStripeTargetV2_Arg)
#define BEEGFS_IOC_MKFILE_STRIPEHINTS _IOW( \
BEEGFS_IOCTYPE_ID, BEEGFS_IOCNUM_MKFILE_STRIPEHINTS, struct BeegfsIoctl_MkFileWithStripeHints_Arg)
BEEGFS_IOCTYPE_ID, BEEGFS_IOCNUM_MKFILE_STRIPEHINTS, \
struct BeegfsIoctl_MkFileWithStripeHints_Arg)
/* used to return the client config file name using an ioctl */
......@@ -102,7 +103,8 @@ struct BeegfsIoctl_MkFile_Arg
int entryNameLen;
int fileType; // see linux/fs.h or man 3 readdir, DT_UNKNOWN, DT_FIFO, ...
const char* symlinkTo; // Only must be set for symlinks. The name a symlink is supposed to point to
const char* symlinkTo; // Only must be set for symlinks.
// The name a symlink is supposed to point to
int symlinkToLen; // Length of the symlink name
int mode; // mode (permission) of the new file
......@@ -135,7 +137,8 @@ struct BeegfsIoctl_MkFileV2_Arg
int entryNameLen;
int fileType; // see linux/fs.h or man 3 readdir, DT_UNKNOWN, DT_FIFO, ...
const char* symlinkTo; // Only must be set for symlinks. The name a symlink is supposed to point to
const char* symlinkTo; // Only must be set for symlinks.
// The name a symlink is supposed to point to
int symlinkToLen; // Length of the symlink name
int mode; // mode (permission) of the new file
......@@ -161,7 +164,7 @@ struct BeegfsIoctl_GetStripeInfo_Arg
struct BeegfsIoctl_GetStripeTarget_Arg
{
uint16_t targetIndex; // index of the target that should be queried (0-based)
uint16_t outTargetNumID; // (out-value) numeric ID of target with given index
uint16_t outNodeNumID; // (out-value) numeric ID of node to which this target is mapped
char outNodeStrID[BEEGFS_IOCTL_NODESTRID_BUFLEN]; /* (out-value) string ID of node to which this
......
......@@ -128,12 +128,18 @@ TICPP_INC_PATH ?= $(BEEGFS_THIRDPARTY_PATH)/source/ticpp
MONGOOSE_INC_PATH ?= $(BEEGFS_THIRDPARTY_PATH)/source/mongoose
BOOST_INC_PATH ?= $(BEEGFS_THIRDPARTY_PATH)/source/boost/
ifneq ($(target_arch),)
STRIP := $(target_arch)-strip
AR := $(target_arch)-ar
CC := $(target_arch)-gcc
CXX := $(target_arch)-g++
endif
SHELL := /bin/bash
STRIP ?= strip
CXX ?= g++
AR ?= ar
AR := ar
# if -T is supported by ar, use it. thin archives are quicker to create and maintain.
ifeq ($(shell ar -TM 2>&1 <<<""),)
AR += -T
......
......@@ -27,9 +27,9 @@ print_usage()
echo " $ `basename $0` [options]"
echo
echo "OPTIONS:"
echo " -v S Major version string (e.g. \"2015.03\")."
echo " -v S Major version string (e.g. \"6\")."
echo " Default is based on current date."
echo " -s S Minor version string (e.g. \"r1\")."
echo " -m S Minor version string (e.g. \"2\")."
echo " Default is based on current date."
echo " -j N Number of parallel processes for \"make\"."
echo " -p S Package destination directory."
......
......@@ -314,10 +314,6 @@ $(call define_if_matches, KERNEL_HAS_GENERIC_PERMISSION_4, \
$(call define_if_matches, KERNEL_HAS_WRITE_ITER, -F "ssize_t (*write_iter)", fs.h)
$(call define_if_matches, KERNEL_HAS_AIO_WRITE_BUF, \
-P "ssize_t \(\*aio_write\).*const char", fs.h)
KERNEL_FEATURE_DETECTION += $(shell \
grep -sFB20 "launder_page" ${KSRCDIR_PRUNED_HEAD}/include/linux/fs.h \
| grep -LF "address_space_operations_ext" | grep -qsvF "input" \
&& echo "-DKERNEL_HAS_LAUNDER_PAGE")
$(call define_if_matches, KERNEL_HAS_INVALIDATEPAGE_RANGE, \
-P "void \(\*invalidatepage\) \(struct page \*. unsigned int. unsigned int\);", fs.h)
$(call define_if_matches, KERNEL_HAS_PERMISSION_2, \
......
......@@ -15,6 +15,21 @@ ifneq ($(KERNELRELEASE),)
# --- kbuild part [START] ---
#
BEEGFS_FEATURE_DETECTION := $(shell $(dir $(lastword $(MAKEFILE_LIST)))/feature-detect.sh)
ifneq ($(lastword $(BEEGFS_FEATURE_DETECTION)),--~~success~~--)
$(error feature detection reported an error)
else
BEEGFS_FEATURE_DETECTION := $(filter-out --~~success~~--,$(BEEGFS_FEATURE_DETECTION))
endif
# ccflags-y was introduced in 2.6.24, earlier kernels use EXTRA_CFLAGS for the same purpose
ifeq ($(origin ccflags-y),file)
ccflags-y += $(BEEGFS_FEATURE_DETECTION)
else
# the client makefile sets this already
override EXTRA_CFLAGS += $(BEEGFS_FEATURE_DETECTION)
endif
# Auto-selection of source files and corresponding target objects
BEEGFS_SOURCES := $(shell find $(obj)/../source -name '*.c')
BEEGFS_SOURCES_STRIPPED := $(subst $(obj)/, , $(BEEGFS_SOURCES) )
......@@ -248,6 +263,7 @@ endif
cp Release.mk $(RELEASE_PATH_CLIENT)/build/Makefile
cp KernelFeatureDetection.mk $(RELEASE_PATH_CLIENT)/build/
cp AutoRebuild.mk $(RELEASE_PATH_CLIENT)/build/
cp feature-detect.sh $(RELEASE_PATH_CLIENT)/build/
mkdir --parents $(RELEASE_PATH_CLIENT)/source/common/net/sock
cp $(BEEGFS_AUTOCONF_BUILD_PATH).in \
......
......@@ -12,6 +12,21 @@ ifneq ($(KERNELRELEASE),)
# --- kbuild part [START] ---
#
BEEGFS_FEATURE_DETECTION := $(shell $(dir $(lastword $(MAKEFILE_LIST)))/feature-detect.sh)
ifneq ($(lastword $(BEEGFS_FEATURE_DETECTION)),--~~success~~--)
$(error feature detection reported an error)
else
BEEGFS_FEATURE_DETECTION := $(filter-out --~~success~~--,$(BEEGFS_FEATURE_DETECTION))
endif
# ccflags-y was introduced in 2.6.24, earlier kernels use EXTRA_CFLAGS for the same purpose
ifeq ($(origin ccflags-y),file)
ccflags-y += $(BEEGFS_FEATURE_DETECTION)
else
# the client makefile sets this already
override EXTRA_CFLAGS += $(BEEGFS_FEATURE_DETECTION)
endif
# Auto-selection of source files and corresponding target objects
BEEGFS_SOURCES := $(shell find $(obj)/../source -name '*.c')
BEEGFS_SOURCES_STRIPPED := $(subst $(obj)/, , $(BEEGFS_SOURCES) )
......
#!/bin/bash
set -e
CFLAGS="-D__KERNEL__ $LINUXINCLUDE $KBUILD_CFLAGS $KBUILD_CPPFLAGS -DKBUILD_BASENAME=\"beegfs\""
_check_struct_field_input() {
local field=$1
shift 1
for i in "$@"; do
echo "#include <$i>"
done
cat <<EOF
void want_symbol(void) {
struct ${field%%::*} s;
(void) (s.${field##*::});
}
EOF
}
check_struct_field() {
local field=$1
local marker=$2
shift 2
if _check_struct_field_input "$field" "$@" | $CC $CFLAGS -x c -o /dev/null -c - 2>/dev/null
then
echo -D$marker
fi
}
cd $srctree
check_struct_field \
address_space_operations::launder_page \
KERNEL_HAS_LAUNDER_PAGE \
linux/fs.h
# we have to communicate with the calling makefile somehow. since we can't really use the return
# code of this script, we'll echo a special string at the end of our output for the caller to
# detect and remove again.
# this string has to be something that will, on its own, never be a valid compiler option. so let's
# choose something really, really unlikely like
echo "--~~success~~--"
......@@ -310,12 +310,13 @@ static int beegfs_release_range(struct file* filp, loff_t first, loff_t last)
int writeRes;
// expand range to fit full pages
first &= PAGE_MASK;
last |= ~PAGE_MASK;
first &= ~PAGE_MASK;
last |= PAGE_MASK;
clear_bit(AS_EIO, &filp->f_mapping->flags);
#if !defined(KERNEL_HAS_FILEMAP_WRITE_AND_WAIT_RANGE)
#if !defined(KERNEL_HAS_FILEMAP_WRITE_AND_WAIT_RANGE) || LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
/* rhel5 kernels declare the *_range symbol, but don't actually have it ... */
writeRes = filemap_write_and_wait(filp->f_mapping);
#else
writeRes = filemap_write_and_wait_range(filp->f_mapping, first, last);
......@@ -339,8 +340,8 @@ static int beegfs_acquire_range(struct file* filp, loff_t first, loff_t last)
int err;
// expand range to fit full pages
first &= PAGE_MASK;
last |= ~PAGE_MASK;
first &= ~PAGE_MASK;
last |= PAGE_MASK;
err = beegfs_release_range(filp, first, last);
if(err)
......
......@@ -1557,6 +1557,12 @@ ssize_t FhgfsOpsRemoting_rwChunkPageVec(FhgfsChunkPageVec *pageVec, RemotingIOIn
if (rwType == BEEGFS_RWTYPE_WRITE)
BitStore_setBit(ioInfo->firstWriteDone, targetIndex, true);
}
else if (retVal == -FhgfsOpsErr_COMMUNICATION)
{
// commkit has done no communication at all, and thus hasn't touched any pages. it is our
// responsibility to end pending io with an error now.
needReadWriteHandlePages = true;
}
LOG_DEBUG_FORMATTED(log, Log_SPAM, logContext, "fileHandleID: %s rwType %s: sum-result %lld",
ioInfo->fileHandleID, rwTypeStr, retVal);
......
......@@ -306,4 +306,10 @@ extern void assertMsg(const char* file, unsigned line, const char* condition);
# define ASSERT(cond) do {} while (0)
#endif
#if defined (__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 24)
#define USE_READDIR_R 0
#else
#define USE_READDIR_R 1
#endif
#endif /*COMMON_H_*/
......@@ -161,7 +161,7 @@ class Atomic
* need the entire preprocessor construct, but disassembling a test program showed
* gcc adds a "lock xadd" command, which is slow)
*/
return __sync_fetch_and_add(&this->atomicValue, 0);
return __sync_fetch_and_add((TemplateType*) &this->atomicValue, 0);
#endif
}
......
......@@ -17,7 +17,7 @@ class Barrier
{
int res = pthread_barrier_destroy(&barrier);
if (res != 0)
throw PThreadException(System::getErrString(res));
std::terminate();
}
Barrier(const Barrier&) = delete;
......
......@@ -24,7 +24,7 @@ class Condition
{
int condRes = pthread_cond_destroy(&condition);
if(unlikely(condRes) )
throw MutexException(System::getErrString(condRes) );
std::terminate();
}
static bool initStaticCondAttr();
......
#include "DisposalCleaner.h"
#include <common/net/message/storage/creating/UnlinkFileMsg.h>
#include <common/net/message/storage/creating/UnlinkFileRespMsg.h>
#include <common/net/message/storage/listing/ListDirFromOffsetMsg.h>
#include <common/net/message/storage/listing/ListDirFromOffsetRespMsg.h>
#include <common/storage/Metadata.h>
#include <common/toolkit/MessagingTk.h>
void DisposalCleaner::run(NodeStore& nodes, const std::function<OnItemFn>& onItem,
const std::function<OnErrorFn>& onError)
{
auto node = nodes.referenceFirstNode();
while (node)
{
FhgfsOpsErr walkRes = walkNode(*node, onItem);
if (walkRes != FhgfsOpsErr_SUCCESS)
onError(*node, walkRes);
node = nodes.referenceNextNode(node);
}
}
FhgfsOpsErr DisposalCleaner::walkNode(Node& node, const std::function<OnItemFn>& onItem)
{
FhgfsOpsErr retVal = FhgfsOpsErr_SUCCESS;
size_t numEntriesThisRound = 0; // received during last RPC round
bool commRes = true;
char* respBuf = NULL;
NetMessage* respMsg = NULL;
ListDirFromOffsetRespMsg* respMsgCast;
FhgfsOpsErr listRes = FhgfsOpsErr_SUCCESS;
unsigned maxOutNames = 50;
StringList* entryNames;
uint64_t currentServerOffset = 0;
do
{
for (int i = 0; i <= 1; i++)
{
// i == 0 -> non-mirrored metadata
// i == 1 -> mirrored metadata
//
// we have to skip mirrored metadata if the node we are looking at is the secondary if its
// group, otherwise we would list mirrored disposal file twice - and attempt to delete them
// twice.
// also, we don't have to list anything if the node is not part of a mirror group at all.
if (i == 1)
{
const uint16_t thisGroup = bgm->getBuddyGroupID(node.getNumID().val());
if (thisGroup == 0)
continue;
if (bgm->getPrimaryTargetID(thisGroup) != node.getNumID().val())
continue;
}
std::string entryID = i == 0
? META_DISPOSALDIR_ID_STR
: META_MIRRORDISPOSALDIR_ID_STR;
EntryInfo entryInfo(node.getNumID(), "", entryID, entryID, DirEntryType_DIRECTORY,
i == 0 ? 0 : ENTRYINFO_FEATURE_BUDDYMIRRORED);
ListDirFromOffsetMsg listMsg(&entryInfo, currentServerOffset, maxOutNames, true);
// request/response
commRes = MessagingTk::requestResponse(
node, &listMsg, NETMSGTYPE_ListDirFromOffsetResp, &respBuf, &respMsg);
if (!commRes)
{
retVal = FhgfsOpsErr_COMMUNICATION;
goto err_cleanup;
}
respMsgCast = (ListDirFromOffsetRespMsg*)respMsg;
listRes = (FhgfsOpsErr)respMsgCast->getResult();
if (listRes != FhgfsOpsErr_SUCCESS)
{
retVal = listRes;
goto err_cleanup;
}
entryNames = &respMsgCast->getNames();
numEntriesThisRound = entryNames->size();
currentServerOffset = respMsgCast->getNewServerOffset();
for (auto it = entryNames->begin(); it != entryNames->end(); ++it)
{
retVal = onItem(node, *it, i != 0);
if (retVal != FhgfsOpsErr_SUCCESS)
break;
}
err_cleanup:
SAFE_DELETE(respMsg);
SAFE_FREE(respBuf);
}
} while (retVal == FhgfsOpsErr_SUCCESS && numEntriesThisRound == maxOutNames);
return retVal;
}
FhgfsOpsErr DisposalCleaner::unlinkFile(Node& node, std::string entryName, const bool isMirrored)
{
FhgfsOpsErr retVal;
bool commRes;
char* respBuf = NULL;
NetMessage* respMsg = NULL;
UnlinkFileRespMsg* respMsgCast;
std::string entryID = isMirrored
? META_MIRRORDISPOSALDIR_ID_STR
: META_DISPOSALDIR_ID_STR;
EntryInfo parentInfo(node.getNumID(), "", entryID, entryID, DirEntryType_DIRECTORY,
isMirrored ? ENTRYINFO_FEATURE_BUDDYMIRRORED : 0);
UnlinkFileMsg getInfoMsg(&parentInfo, entryName);
// request/response
commRes = MessagingTk::requestResponse(
node, &getInfoMsg, NETMSGTYPE_UnlinkFileResp, &respBuf, &respMsg);
if (!commRes)
{
retVal = FhgfsOpsErr_COMMUNICATION;
goto err_cleanup;
}
respMsgCast = (UnlinkFileRespMsg*)respMsg;
retVal = (FhgfsOpsErr)respMsgCast->getValue();
err_cleanup:
SAFE_DELETE(respMsg);
SAFE_FREE(respBuf);
return retVal;
}
#ifndef DISPOSALCLEANER_H
#define DISPOSALCLEANER_H
#include <common/nodes/MirrorBuddyGroupMapper.h>
#include <common/nodes/Node.h>
#include <common/nodes/NodeStore.h>
#include <functional>
class DisposalCleaner
{
public:
typedef FhgfsOpsErr (OnItemFn)(Node& owner, const std::string& entryID,
const bool isMirrored);
typedef void (OnErrorFn)(Node& node, FhgfsOpsErr err);
DisposalCleaner(MirrorBuddyGroupMapper& bgm):
bgm(&bgm)
{
}
void run(NodeStore& nodes, const std::function<OnItemFn>& onItem,
const std::function<OnErrorFn>& onError);
static FhgfsOpsErr unlinkFile(Node& node, std::string entryName, const bool isMirrored);
private:
MirrorBuddyGroupMapper* bgm;
FhgfsOpsErr walkNode(Node& node, const std::function<OnItemFn>& onItem);
};
#endif
......@@ -111,6 +111,9 @@ class NetFilter
for(size_t i = 0; i < this->filterArrayLen; i++)
{
if (filterArray[i].shiftBitsNum == 32)
return true;
// note: stored addresses are in host byte order to enable correct shift operator usage
const in_addr_t ipHostOrderShifted =
ipHostOrder >> ( (this->filterArray)[i].shiftBitsNum);
......
......@@ -641,7 +641,7 @@ void TestSerialization::testStatData()
(
fmt & (StatDataFormat_Flag_HasFlags | StatDataFormat_Flag_IsNet)
? a.flags == b.flags
&& a.settableFileAttribs.mode == a.settableFileAttribs.mode
&& a.settableFileAttribs.mode == b.settableFileAttribs.mode
&& (fmt & StatDataFormat_Flag_IsNet
? true // numBlocks comparison is spurious
: a.getIsSparseFile()
......
......@@ -202,7 +202,7 @@ void FsckDBFileInodesTable::insert(FsckFileInodeList& fileInodes, const BulkHand
if(offsetInPattern == extraTargets.NTARGETS - 1)
{
if(handle)
handle->second->append(extraTargets);
std::get<1>(*handle)->append(extraTargets);
else
this->targets.insert(extraTargets);
......@@ -213,9 +213,9 @@ void FsckDBFileInodesTable::insert(FsckFileInodeList& fileInodes, const BulkHand
if(handle)
{
handle->first->append(inode);
std::get<0>(*handle)->append(inode);
if(extraTargets.firstTargetIndex != 0)
handle->second->append(extraTargets);
std::get<1>(*handle)->append(extraTargets);
}
else
{
......
......@@ -270,7 +270,7 @@ class FsckDBDentryTable
class FsckDBFileInodesTable
{
public:
typedef std::pair<
typedef std::tuple<
boost::shared_ptr<Buffer<db::FileInode> >,
boost::shared_ptr<Buffer<db::StripeTargets> > > BulkHandle;
......
#include "ModeCheckFS.h"
#include <common/toolkit/DisposalCleaner.h>
#include <common/toolkit/ListTk.h>
#include <common/toolkit/UnitTk.h>
#include <common/toolkit/ZipIterator.h>
......@@ -81,6 +82,21 @@ FsckRepairAction UserPrompter::chooseAction(const std::string& prompt)
return repairAction;
}
static FhgfsOpsErr handleDisposalItem(Node& owner, const std::string& entryID,
const bool isMirrored)
{
FhgfsOpsErr err = DisposalCleaner::unlinkFile(owner, entryID, isMirrored);
if (err == FhgfsOpsErr_INUSE)
return FhgfsOpsErr_SUCCESS;
else
return err;
}
static void handleDisposalError(Node& node, FhgfsOpsErr err, uint64_t& errors)
{
errors += 1;
}
ModeCheckFS::ModeCheckFS()
......@@ -183,6 +199,8 @@ int ModeCheckFS::execute()
if (initDBRes)
return initDBRes;
disposeUnusedFiles();
boost::scoped_ptr<ModificationEventHandler> modificationEventHandler;
if (!cfg->getRunOffline())
......@@ -397,9 +415,33 @@ void ModeCheckFS::printHeaderInformation()
+ cfg->getDatabasePath(), OutputOptions_LINEBREAK | OutputOptions_HEADLINE);
}
void ModeCheckFS::disposeUnusedFiles()
{
Config* cfg = Program::getApp()->getConfig();
if (cfg->getReadOnly() || cfg->getNoFetch())
return;
FsckTkEx::fsckOutput("Step 2: Delete unused files from disposal: ", OutputOptions_NONE);
using namespace std::placeholders;
uint64_t errors = 0;
DisposalCleaner dc(*Program::getApp()->getMetaMirrorBuddyGroupMapper());
dc.run(*Program::getApp()->getMetaNodes(),
handleDisposalItem,
std::bind(handleDisposalError, _1, _2, std::ref(errors)));
if (errors > 0)
FsckTkEx::fsckOutput("Some files could not be deleted.");
else
FsckTkEx::fsckOutput("Finished.");
}
FhgfsOpsErr ModeCheckFS::gatherData(bool forceRestart)
{
FsckTkEx::fsckOutput("Step 2: Gather data from nodes: ", OutputOptions_DOUBLELINEBREAK);
FsckTkEx::fsckOutput("Step 3: Gather data from nodes: ", OutputOptions_DOUBLELINEBREAK);
DataFetcher dataFetcher(*this->database, forceRestart);
const FhgfsOpsErr retVal = dataFetcher.execute();
......@@ -862,7 +904,7 @@ void ModeCheckFS::repairMalformedChunk(FsckChunk& chunk, UserPrompter& prompt)
void ModeCheckFS::checkAndRepair()
{
FsckTkEx::fsckOutput("Step 3: Check for errors... ", OutputOptions_DOUBLELINEBREAK);
FsckTkEx::fsckOutput("Step 4: Check for errors... ", OutputOptions_DOUBLELINEBREAK);
Config* cfg = Program::getApp()->getConfig();
......
......@@ -51,6 +51,7 @@ class ModeCheckFS : public Mode
int initDatabase();
void printHeaderInformation();
void disposeUnusedFiles();
FhgfsOpsErr gatherData(bool forceRestart);
template<typename Obj, typename State>
......
......@@ -119,13 +119,19 @@ FhgfsOpsErr BuddyResyncerBulkSyncSlave::streamCandidateDir(Socket& socket,
return FhgfsOpsErr_INTERNAL;
}
struct dirent entryBuf;
while (true)
{
struct dirent* entry;
if (::readdir_r(dir.get(), &entryBuf, &entry) < 0)
#if USE_READDIR_P
struct dirent entryBuf;
int err = ::readdir_r(dir.get(), &entryBuf, &entry);
#else
errno = 0;
entry = readdir(dir.get());
int err = entry ? 0 : errno;
#endif
if (err > 0)
{
LOG(ERR, "Could not read candidate directory.", candidatePath, sysErr());
numDirErrors.increase();
......
......@@ -55,10 +55,16 @@ void BuddyResyncerGatherSlave::crawlDir(const std::string& path, const MetaSyncD
while (!getSelfTerminate())
{
struct dirent buffer;
struct dirent* entry;
#if USE_READDIR_R
struct dirent buffer;
const int readRes = ::readdir_r(dirHandle.get(), &buffer, &entry);
#else
errno = 0;
entry = ::readdir(dirHandle.get());
const int readRes = entry ? 0 : errno;
#endif
if (readRes != 0)