Merge pull request #22370 from taosdata/FIX/TD-25605-3.0

enh: check if disk space sufficient at primary dir with tfs
This commit is contained in:
Hui Li 2023-08-09 18:32:07 +08:00 committed by GitHub
commit 10f5d223bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 118 additions and 37 deletions

View File

@ -300,6 +300,25 @@ void tfsClosedir(STfsDir *pDir);
*/ */
int32_t tfsGetMonitorInfo(STfs *pTfs, SMonDiskInfo *pInfo); int32_t tfsGetMonitorInfo(STfs *pTfs, SMonDiskInfo *pInfo);
/**
* @brief Check if disk space available at level
*
* @param pTfs The fs object.
* #param level the level
* @return bool
*/
bool tfsDiskSpaceAvailable(STfs *pTfs, int32_t level);
/**
* @brief Check if disk space sufficient at disk of level
*
* @param pTfs The fs object.
* @param level the level
* @param disk the disk
* @return bool
*/
bool tfsDiskSpaceSufficient(STfs *pTfs, int32_t level, int32_t disk);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -460,7 +460,6 @@ static void vmCleanup(SVnodeMgmt *pMgmt) {
vmCloseVnodes(pMgmt); vmCloseVnodes(pMgmt);
vmStopWorker(pMgmt); vmStopWorker(pMgmt);
vnodeCleanup(); vnodeCleanup();
tfsClose(pMgmt->pTfs);
taosThreadRwlockDestroy(&pMgmt->lock); taosThreadRwlockDestroy(&pMgmt->lock);
taosMemoryFree(pMgmt); taosMemoryFree(pMgmt);
} }
@ -535,20 +534,9 @@ static int32_t vmInit(SMgmtInputOpt *pInput, SMgmtOutputOpt *pOutput) {
pMgmt->msgCb.mgmt = pMgmt; pMgmt->msgCb.mgmt = pMgmt;
taosThreadRwlockInit(&pMgmt->lock, NULL); taosThreadRwlockInit(&pMgmt->lock, NULL);
SDiskCfg dCfg = {0}; pMgmt->pTfs = pInput->pTfs;
tstrncpy(dCfg.dir, tsDataDir, TSDB_FILENAME_LEN);
dCfg.level = 0;
dCfg.primary = 1;
SDiskCfg *pDisks = tsDiskCfg;
int32_t numOfDisks = tsDiskCfgNum;
if (numOfDisks <= 0 || pDisks == NULL) {
pDisks = &dCfg;
numOfDisks = 1;
}
pMgmt->pTfs = tfsOpen(pDisks, numOfDisks);
if (pMgmt->pTfs == NULL) { if (pMgmt->pTfs == NULL) {
dError("failed to init tfs since %s", terrstr()); dError("tfs is null.");
goto _OVER; goto _OVER;
} }
tmsgReportStartup("vnode-tfs", "initialized"); tmsgReportStartup("vnode-tfs", "initialized");

View File

@ -15,6 +15,7 @@
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include "vmInt.h" #include "vmInt.h"
#include "vnodeInt.h"
static inline void vmSendRsp(SRpcMsg *pMsg, int32_t code) { static inline void vmSendRsp(SRpcMsg *pMsg, int32_t code) {
if (pMsg->info.handle == NULL) return; if (pMsg->info.handle == NULL) return;
@ -159,6 +160,15 @@ static void vmSendResponse(SRpcMsg *pMsg) {
} }
} }
static bool vmDataSpaceSufficient(SVnodeObj *pVnode) {
STfs *pTfs = pVnode->pImpl->pTfs;
if (pTfs) {
return tfsDiskSpaceSufficient(pTfs, 0, pVnode->diskPrimary);
} else {
return osDataSpaceSufficient();
}
}
static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtype) { static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtype) {
const STraceId *trace = &pMsg->info.traceId; const STraceId *trace = &pMsg->info.traceId;
if (pMsg->contLen < sizeof(SMsgHead)) { if (pMsg->contLen < sizeof(SMsgHead)) {
@ -204,7 +214,7 @@ static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtyp
taosWriteQitem(pVnode->pFetchQ, pMsg); taosWriteQitem(pVnode->pFetchQ, pMsg);
break; break;
case WRITE_QUEUE: case WRITE_QUEUE:
if (!osDataSpaceSufficient()) { if (!vmDataSpaceSufficient(pVnode)) {
terrno = TSDB_CODE_NO_ENOUGH_DISKSPACE; terrno = TSDB_CODE_NO_ENOUGH_DISKSPACE;
code = terrno; code = terrno;
dError("vgId:%d, msg:%p put into vnode-write queue failed since %s", pVnode->vgId, pMsg, terrstr(code)); dError("vgId:%d, msg:%p put into vnode-write queue failed since %s", pVnode->vgId, pMsg, terrstr(code));

View File

@ -20,6 +20,7 @@
#include "uv.h" #include "uv.h"
#include "dmInt.h" #include "dmInt.h"
#include "tfs.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -79,6 +80,7 @@ typedef struct SDnode {
TdThreadMutex mutex; TdThreadMutex mutex;
TdFilePtr lockfile; TdFilePtr lockfile;
SDnodeData data; SDnodeData data;
STfs *pTfs;
SMgmtWrapper wrappers[NODE_END]; SMgmtWrapper wrappers[NODE_END];
} SDnode; } SDnode;
@ -124,4 +126,4 @@ void dmGetQnodeLoads(SQnodeLoad *pInfo);
} }
#endif #endif
#endif /*_TD_DND_MGMT_H_*/ #endif /*_TD_DND_MGMT_H_*/

View File

@ -96,28 +96,23 @@ _exit:
return code; return code;
} }
static bool dmCheckDiskSpace() { static bool dmDataSpaceAvailable() {
osUpdate(); SDnode *pDnode = dmInstance();
// sufficiency if (pDnode->pTfs) {
if (!osDataSpaceSufficient()) { return tfsDiskSpaceAvailable(pDnode->pTfs, 0);
dWarn("free data disk size: %f GB, not sufficient, expected %f GB at least",
(double)tsDataSpace.size.avail / 1024.0 / 1024.0 / 1024.0,
(double)tsDataSpace.reserved / 1024.0 / 1024.0 / 1024.0);
} }
if (!osLogSpaceSufficient()) {
dWarn("free log disk size: %f GB, not sufficient, expected %f GB at least",
(double)tsLogSpace.size.avail / 1024.0 / 1024.0 / 1024.0,
(double)tsLogSpace.reserved / 1024.0 / 1024.0 / 1024.0);
}
if (!osTempSpaceSufficient()) {
dWarn("free temp disk size: %f GB, not sufficient, expected %f GB at least",
(double)tsTempSpace.size.avail / 1024.0 / 1024.0 / 1024.0,
(double)tsTempSpace.reserved / 1024.0 / 1024.0 / 1024.0);
}
// availability
bool ret = true;
if (!osDataSpaceAvailable()) { if (!osDataSpaceAvailable()) {
dError("data disk space unavailable, i.e. %s", tsDataDir); dError("data disk space unavailable, i.e. %s", tsDataDir);
return false;
}
return true;
}
static bool dmCheckDiskSpace() {
osUpdate();
// availability
bool ret = true;
if (!dmDataSpaceAvailable()) {
terrno = TSDB_CODE_NO_DISKSPACE; terrno = TSDB_CODE_NO_DISKSPACE;
ret = false; ret = false;
} }
@ -134,6 +129,34 @@ static bool dmCheckDiskSpace() {
return ret; return ret;
} }
int32_t dmDiskInit() {
SDnode *pDnode = dmInstance();
SDiskCfg dCfg = {0};
tstrncpy(dCfg.dir, tsDataDir, TSDB_FILENAME_LEN);
dCfg.level = 0;
dCfg.primary = 1;
SDiskCfg *pDisks = tsDiskCfg;
int32_t numOfDisks = tsDiskCfgNum;
if (numOfDisks <= 0 || pDisks == NULL) {
pDisks = &dCfg;
numOfDisks = 1;
}
pDnode->pTfs = tfsOpen(pDisks, numOfDisks);
if (pDnode->pTfs == NULL) {
dError("failed to init tfs since %s", terrstr());
return -1;
}
return 0;
}
int32_t dmDiskClose() {
SDnode *pDnode = dmInstance();
tfsClose(pDnode->pTfs);
pDnode->pTfs = NULL;
return 0;
}
static bool dmCheckDataDirVersion() { static bool dmCheckDataDirVersion() {
char checkDataDirJsonFileName[PATH_MAX] = {0}; char checkDataDirJsonFileName[PATH_MAX] = {0};
snprintf(checkDataDirJsonFileName, PATH_MAX, "%s/dnode/dnodeCfg.json", tsDataDir); snprintf(checkDataDirJsonFileName, PATH_MAX, "%s/dnode/dnodeCfg.json", tsDataDir);
@ -147,6 +170,7 @@ static bool dmCheckDataDirVersion() {
int32_t dmInit() { int32_t dmInit() {
dInfo("start to init dnode env"); dInfo("start to init dnode env");
if (dmDiskInit() != 0) return -1;
if (!dmCheckDataDirVersion()) return -1; if (!dmCheckDataDirVersion()) return -1;
if (!dmCheckDiskSpace()) return -1; if (!dmCheckDiskSpace()) return -1;
if (dmCheckRepeatInit(dmInstance()) != 0) return -1; if (dmCheckRepeatInit(dmInstance()) != 0) return -1;
@ -177,6 +201,7 @@ void dmCleanup() {
udfcClose(); udfcClose();
udfStopUdfd(); udfStopUdfd();
taosStopCacheRefreshWorker(); taosStopCacheRefreshWorker();
dmDiskClose();
dInfo("dnode env is cleaned up"); dInfo("dnode env is cleaned up");
taosCleanupCfg(); taosCleanupCfg();
@ -367,6 +392,7 @@ SMgmtInputOpt dmBuildMgmtInputOpt(SMgmtWrapper *pWrapper) {
SMgmtInputOpt opt = { SMgmtInputOpt opt = {
.path = pWrapper->path, .path = pWrapper->path,
.name = pWrapper->name, .name = pWrapper->name,
.pTfs = pWrapper->pDnode->pTfs,
.pData = &pWrapper->pDnode->data, .pData = &pWrapper->pDnode->data,
.processCreateNodeFp = dmProcessCreateNodeReq, .processCreateNodeFp = dmProcessCreateNodeReq,
.processAlterNodeTypeFp = dmProcessAlterNodeTypeReq, .processAlterNodeTypeFp = dmProcessAlterNodeTypeReq,

View File

@ -37,6 +37,7 @@
#include "monitor.h" #include "monitor.h"
#include "qnode.h" #include "qnode.h"
#include "sync.h" #include "sync.h"
#include "tfs.h"
#include "wal.h" #include "wal.h"
#include "libs/function/tudf.h" #include "libs/function/tudf.h"
@ -111,6 +112,7 @@ typedef struct {
typedef struct { typedef struct {
const char *path; const char *path;
const char *name; const char *name;
STfs *pTfs;
SDnodeData *pData; SDnodeData *pData;
SMsgCb msgCb; SMsgCb msgCb;
ProcessCreateNodeFp processCreateNodeFp; ProcessCreateNodeFp processCreateNodeFp;

View File

@ -14,6 +14,7 @@
*/ */
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include "osEnv.h"
#include "tfsInt.h" #include "tfsInt.h"
static int32_t tfsMount(STfs *pTfs, SDiskCfg *pCfg); static int32_t tfsMount(STfs *pTfs, SDiskCfg *pCfg);
@ -113,6 +114,39 @@ SDiskSize tfsGetSize(STfs *pTfs) {
return size; return size;
} }
bool tfsDiskSpaceAvailable(STfs *pTfs, int32_t level) {
if (level < 0 || level >= pTfs->nlevel) {
return false;
}
STfsTier *pTier = TFS_TIER_AT(pTfs, level);
for (int32_t id = 0; id < pTier->ndisk; id++) {
SDiskID diskId = {.level = level, .id = id};
STfsDisk *pDisk = TFS_DISK_AT(pTfs, diskId);
if (pDisk == NULL) {
return false;
}
if (pDisk->size.avail <= 0) {
fError("tfs disk space unavailable. level:%d, disk:%d, path:%s", level, id, pDisk->path);
return false;
}
}
return true;
}
bool tfsDiskSpaceSufficient(STfs *pTfs, int32_t level, int32_t disk) {
if (level < 0 || level >= pTfs->nlevel) {
return false;
}
STfsTier *pTier = TFS_TIER_AT(pTfs, level);
if (disk < 0 || disk >= pTier->ndisk) {
return false;
}
SDiskID diskId = {.level = level, .id = disk};
STfsDisk *pDisk = TFS_DISK_AT(pTfs, diskId);
return pDisk->size.avail >= tsDataSpace.reserved;
}
int32_t tfsGetDisksAtLevel(STfs *pTfs, int32_t level) { int32_t tfsGetDisksAtLevel(STfs *pTfs, int32_t level) {
if (level < 0 || level >= pTfs->nlevel) { if (level < 0 || level >= pTfs->nlevel) {
return 0; return 0;

View File

@ -95,10 +95,10 @@ void osCleanup() {}
bool osLogSpaceAvailable() { return tsLogSpace.size.avail > 0; } bool osLogSpaceAvailable() { return tsLogSpace.size.avail > 0; }
bool osDataSpaceAvailable() { return tsDataSpace.size.avail > 0; }
bool osTempSpaceAvailable() { return tsTempSpace.size.avail > 0; } bool osTempSpaceAvailable() { return tsTempSpace.size.avail > 0; }
bool osDataSpaceAvailable() { return tsDataSpace.size.avail > 0; }
bool osLogSpaceSufficient() { return tsLogSpace.size.avail > tsLogSpace.reserved; } bool osLogSpaceSufficient() { return tsLogSpace.size.avail > tsLogSpace.reserved; }
bool osDataSpaceSufficient() { return tsDataSpace.size.avail > tsDataSpace.reserved; } bool osDataSpaceSufficient() { return tsDataSpace.size.avail > tsDataSpace.reserved; }