Fix: 1.quota list optimization

2.The path of quota update is consistent, but the inode is inconsistent, so it needs to fail
     3.To delete the rootquota directory, you need to delete the quota first
     4.Solve the problem that the quota has been deleted, but after restarting the master, the quota reappears
Signed-off-by: baijiaruo <huyao2@oppo.com>
This commit is contained in:
baijiaruo 2023-04-06 11:20:35 +08:00 committed by leonrayang
parent 342233ac00
commit 7bccbc4ea2
12 changed files with 70 additions and 16 deletions

View File

@ -617,3 +617,24 @@ func formatZoneView(zv *proto.ZoneView) string {
}
return sb.String()
}
var quotaTableRowPattern = "%-6v %-30v %-15v %-8v %-10v %-10v %-10v %-12v %-12v %-10v %-10v %-10v %-10v"
func formatQuotaTableHeader() string {
return fmt.Sprintf(quotaTableRowPattern, "ID", "PATH", "VOL", "STATUS", "CTIME",
"PID", "RINODE", "LIMITEDFILES", "LIMITEDBYTES", "USEDFILES", "USEDBYTES", "MAXFILES", "MAXBYTES")
}
func formatQuotaInfo(info *proto.QuotaInfo) string {
var status string
if info.Status == proto.QuotaInit {
status = "Init"
} else if info.Status == proto.QuotaComplete {
status = "Complete"
} else {
status = "Deleting"
}
return fmt.Sprintf(quotaTableRowPattern, info.QuotaId, info.FullPath, info.VolName, status, info.CTime, info.PartitionId,
info.RootInode, info.LimitedInfo.LimitedFiles, info.LimitedInfo.LimitedBytes, info.UsedInfo.UsedFiles, info.UsedInfo.UsedBytes,
info.MaxFiles, info.MaxBytes)
}

View File

@ -105,7 +105,8 @@ func newQuotaSetCmd(client *master.MasterClient) *cobra.Command {
stdout("volName %v path %v quota set failed(%v)\n", volName, fullPath, err)
return
}
stdout("volName %v path %v maxFiles %v, maxBytes %v err %v.\n", volName, fullPath, maxFiles, maxBytes, err)
stdout("setQuota: volName %v path %v inode %v maxFiles %v maxBytes %v success.\n",
volName, fullPath, inodeId, maxFiles, maxBytes)
},
}
cmd.Flags().Uint64Var(&maxFiles, CliFlagMaxFiles, cmdQuotaDefaultMaxFiles, "Specify quota max files")
@ -126,8 +127,10 @@ func newQuotaListCmd(client *master.MasterClient) *cobra.Command {
stdout("volName %v quota list failed(%v)\n", volName, err)
return
}
stdout("[quotas]\n")
stdout("%v\n", formatQuotaTableHeader())
for _, quotaInfo := range quotas {
stdout("quotas:%v\n", *quotaInfo)
stdout("%v\n", formatQuotaInfo(quotaInfo))
}
},
}
@ -168,7 +171,8 @@ func newQuotaUpdateCmd(client *master.MasterClient) *cobra.Command {
stdout("volName %v path %v quota update failed(%v)\n", volName, fullPath, err)
return
}
stdout("volName %v path %v maxFiles %v, maxBytes %v err %v.\n", volName, fullPath, maxFiles, maxBytes, err)
stdout("updateQuota: volName %v path %v inode %v maxFiles %v maxBytes %v success.\n",
volName, fullPath, inodeId, maxFiles, maxBytes)
},
}
cmd.Flags().Uint64Var(&maxFiles, CliFlagMaxFiles, cmdQuotaDefaultMaxFiles, "Specify quota max files")

View File

@ -43,7 +43,9 @@ func (s *Super) InodeGet(ino uint64) (*proto.InodeInfo, error) {
}
}
s.ic.Put(info)
s.fslock.Lock()
node, isFind := s.nodeCache[ino]
s.fslock.Unlock()
if isFind {
if proto.IsDir(info.Mode) {
node.(*Dir).info = info

View File

@ -525,15 +525,15 @@ func (c *Cluster) checkMetaNodeHeartbeat() {
}
spaceInfo := vol.uidSpaceManager.getSpaceOp()
hbReq.UidLimitInfo = append(hbReq.UidLimitInfo, spaceInfo...)
quotaHbInfos := vol.quotaManager.getQuotaHbInfos()
hbReq.QuotaHbInfos = append(hbReq.QuotaHbInfos, quotaHbInfos...)
log.LogDebugf("checkMetaNodeHeartbeat start")
for _, info := range hbReq.QuotaHbInfos {
log.LogDebugf("checkMetaNodeHeartbeat info [%v]", info)
if len(quotaHbInfos) != 0 {
hbReq.QuotaHbInfos = append(hbReq.QuotaHbInfos, quotaHbInfos...)
}
}
log.LogDebugf("checkMetaNodeHeartbeat start")
for _, info := range hbReq.QuotaHbInfos {
log.LogDebugf("checkMetaNodeHeartbeat info [%v]", info)
}
tasks = append(tasks, task)
return true
})

View File

@ -1177,7 +1177,7 @@ func (c *Cluster) dealDeleteMetaserverQuotaResponse(nodeAddr string, resp *proto
metadata.Op = opSyncDeleteQuota
metadata.K = quotaPrefix + strconv.FormatUint(vol.ID, 10) + keySeparator + strconv.FormatUint(uint64(resp.QuotaId), 10)
metadata.V = value
log.LogInfof("hytemp dealSetMetaserverQuotaResponse op [%v] k [%v]", metadata.Op, metadata.K)
if err = c.submit(metadata); err != nil {
log.LogErrorf("delete quota [%v] submit fail [%v].", quotaInfo, err)
return

View File

@ -51,6 +51,7 @@ func (alloc *IDAllocator) restore() {
alloc.restoreMaxMetaPartitionID()
alloc.restoreMaxCommonID()
alloc.restoreClientID()
alloc.restoreMaxQuotaID()
}
func (alloc *IDAllocator) restoreClientID() {

View File

@ -109,6 +109,12 @@ func (mqMgr *MasterQuotaManager) updateQuota(req *proto.UpdateMasterQuotaReuqest
return
}
if quotaInfo.RootInode != req.Inode {
log.LogErrorf("vol [%v] update quota inode [%v] is not match.", mqMgr.vol.Name, req.Inode)
err = errors.New("quota inode is not match.")
return
}
quotaInfo.MaxFiles = req.MaxFiles
quotaInfo.MaxBytes = req.MaxBytes
@ -285,12 +291,14 @@ func (mqMgr *MasterQuotaManager) quotaUpdate(report *proto.MetaPartitionReport)
defer mqMgr.Unlock()
mpId := report.PartitionID
mqMgr.MpQuotaInfoMap[mpId] = report.QuotaReportInfos
log.LogDebugf("[quotaUpdate] mpId [%v] QuotaReportInfos [%v] leader [%v]", mpId, report.QuotaReportInfos, report.IsLeader)
if !report.IsLeader {
return
}
mqMgr.MpQuotaInfoMap[mpId] = report.QuotaReportInfos
for _, quotaInfo = range mqMgr.IdQuotaInfoMap {
quotaInfo.UsedInfo.UsedFiles = 0
quotaInfo.UsedInfo.UsedBytes = 0

View File

@ -102,7 +102,7 @@ func unmarshalTaskResponse(task *proto.AdminTask) (err error) {
response = &proto.MetaPartitionDecommissionResponse{}
case proto.OpMasterSetInodeQuota:
response = &proto.BatchSetMetaserverQuotaResponse{}
case proto.OpMetaBatchDeleteInodeQuota:
case proto.OpMasterDeleteInodeQuota:
response = &proto.BatchDeleteMetaserverQuotaResponse{}
default:
log.LogError(fmt.Sprintf("unknown operate code(%v)", task.OpCode))

View File

@ -1273,7 +1273,7 @@ func (vol *Vol) initQuotaManager(c *Cluster) (err error) {
log.LogErrorf("initQuotaManager Unmarshal fail err [%v]", err)
return err
}
log.LogDebugf("loadQuota info [%v]", quotaInfo)
if vol.Name != quotaInfo.VolName {
panic("vol name do not match")
}

View File

@ -1924,6 +1924,7 @@ func (m *metadataManager) OpMasterSetInodeQuota(conn net.Conn, p *Packet, remote
adminTask := &proto.AdminTask{
Request: req,
}
log.LogInfof("[OpMasterSetInodeQuota] req [%v] start.", req)
decode := json.NewDecoder(bytes.NewBuffer(p.Data))
decode.UseNumber()
@ -1946,6 +1947,9 @@ func (m *metadataManager) OpMasterSetInodeQuota(conn net.Conn, p *Packet, remote
if !m.serveProxy(conn, mp, p) {
return
}
m.responseAckOKToMaster(conn, p)
resp := &proto.BatchSetMetaserverQuotaResponse{
PartitionId: req.PartitionId,
QuotaId: req.QuotaId,
@ -1964,6 +1968,7 @@ func (m *metadataManager) OpMasterDeleteInodeQuota(conn net.Conn, p *Packet, rem
adminTask := &proto.AdminTask{
Request: req,
}
log.LogInfof("[OpMasterDeleteInodeQuota] req [%v] start.", req)
decode := json.NewDecoder(bytes.NewBuffer(p.Data))
decode.UseNumber()
@ -1984,6 +1989,9 @@ func (m *metadataManager) OpMasterDeleteInodeQuota(conn net.Conn, p *Packet, rem
if !m.serveProxy(conn, mp, p) {
return
}
m.responseAckOKToMaster(conn, p)
resp := &proto.BatchDeleteMetaserverQuotaResponse{
PartitionId: req.PartitionId,
QuotaId: req.QuotaId,
@ -1992,7 +2000,6 @@ func (m *metadataManager) OpMasterDeleteInodeQuota(conn net.Conn, p *Packet, rem
adminTask.Response = resp
adminTask.Request = nil
_ = m.respondToMaster(adminTask)
log.LogInfof("[OpMasterDeleteInodeQuota] req [%v] resp [%v] success.", req, resp)
return err
}

View File

@ -347,9 +347,9 @@ func (mp *metaPartition) statisticExtendByLoad(extend *Extend) {
value, isFind := mqMgr.statisticBase.Load(quotaId)
if isFind {
baseInfo = value.(proto.QuotaUsedInfo)
baseInfo.UsedBytes += int64(ino.Size)
baseInfo.UsedFiles += 1
}
baseInfo.UsedBytes += int64(ino.Size)
baseInfo.UsedFiles += 1
mqMgr.statisticBase.Store(quotaId, baseInfo)
log.LogDebugf("[statisticExtendByLoad] quotaId [%v] baseInfo [%v]", quotaId, baseInfo)
}

View File

@ -597,6 +597,17 @@ func (mw *MetaWrapper) delete_ll(parentID uint64, name string, isDir bool) (*pro
if info == nil || info.Nlink > 2 {
return nil, syscall.ENOTEMPTY
}
quotaInfos, err := mw.GetInodeQuota_ll(inode)
if err != nil {
log.LogErrorf("get inode [%v] quota failed [%v]", inode, err)
return nil, syscall.ENOENT
}
for _, info := range quotaInfos {
if info.RootInode == inode {
log.LogErrorf("can not remove quota Root inode equal inode [%v]", inode)
return nil, syscall.EACCES
}
}
}
status, inode, err = mw.ddelete(parentMP, parentID, name)