Bug 1735740

Summary: [cgroup_v2] Cannot get and set cpu cgroup params due to cpu.max error
Product: Red Hat Enterprise Linux Advanced Virtualization Reporter: yisun
Component: libvirtAssignee: Pavel Hrdina <phrdina>
Status: CLOSED ERRATA QA Contact: yisun
Severity: high Docs Contact:
Priority: high    
Version: 8.1CC: jdenemar, lmen, xuzhang, yisun
Target Milestone: rc   
Target Release: 8.0   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: libvirt-5.6.0-3.el8 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of:
: 1741837 (view as bug list) Environment:
Last Closed: 2019-11-06 07:18:12 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1513930, 1741837    

Description yisun 2019-08-01 11:31:07 UTC
Description of problem:
[cgroup_v2] Cannot get and set cpu cgroup params due to format error


Version-Release number of selected component (if applicable):
libvirt-5.5.0-2.module+el8.1.0+3773+7dd501bf.x86_64

How reproducible:
100%

Steps to Reproduce:
0. enable cgroup v2
1. having a running vm
# virsh list
 Id   Name             State
--------------------------------
 1    avocado-vt-vm1   running

2. using 'virsh schedinfo' to get its cpu related cgroup values
# virsh schedinfo avocado-vt-vm1
Scheduler      : posix
error: internal error: Failed to parse value 'max 100000' from cpu.max.
<===== error happened


Additional info:
1. cgroup cpu.max default value is:
# cat /sys/fs/cgroup/machine.slice/machine-qemu\\x2d6\\x2davocado\\x2dvt\\x2dvm1.scope/cpu.max 
max 10000

2. libvirtd log's error as follow:
2019-08-01 08:15:47.218+0000: 1750: error : virCgroupV2GetCpuCfsQuota:1590 : internal error: Failed to parse value 'max 100000' from cpu.max.

3.$vim cat src/util/vircgroupv2.c
1574 static int                                                                      
1575 virCgroupV2GetCpuCfsQuota(virCgroupPtr group,                                   
1576 |   |   |   |   |   |   | long long *cfs_quota)                                 
1577 {                                                                               
1578 |   VIR_AUTOFREE(char *) str = NULL;                                            
1579                                                                                 
1580 |   if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPU,                  
1581 |   |   |   |   |   |   |   |"cpu.max", &str) < 0) {                            
1582 |   |   return -1;                                                              
1583 |   }                                                                           
1584                                                                                 
1585 |   if (STREQLEN(str, "max", 3))                                                
1586 |   |   *cfs_quota = ULLONG_MAX / 1000;                                         
1587                                                                                 
1588 |   if (virStrToLong_ll(str, NULL, 10, cfs_quota) < 0) {                        
1589 |   |   virReportError(VIR_ERR_INTERNAL_ERROR,                                  
1590 |   |   |   |   |   |  _("Failed to parse value '%s' from cpu.max."), str);     
1591 |   |   return -1;                                                              
1592 |   }                                                                           
1593                                                                                 
1594 |   return 0;                                                                   
1595 }                                                                               
<===== in line 1588 the str="max 10000", and this will lead "virStrToLong_ll" to return a '-1' due to:
$ vim src/util/virstring.c
 530 int                                                                             
 531 virStrToLong_ll(char const *s, char **end_ptr, int base, long long *result)     
 532 {                                                                               
 533 |   long long val;                                                              
 534 |   char *p;                                                                    
 535 |   int err;                                                                    
 536                                                                                 
 537 |   errno = 0;                                                                  
 538 |   val = strtoll(s, &p, base); /* exempt from syntax-check */                  
 539 |   err = (errno || (!end_ptr && *p) || p == s);                                
 540 |   if (end_ptr)                                                                
 541 |   |   *end_ptr = p;                                                           
 542 |   if (err)                                                                    
 543 |   |   return -1;                                                              
 544 |   *result = val;                                                              
 545 |   return 0;                                                                   
 546 }  
<===== line 538 will be "strtoll("max 10000", &p, 10)", then 'p' will equal to 'max 10000', so line 539 "!end_ptr && *p" and "p==s" will both be true so '-1' will be returned later.

Comment 1 yisun 2019-08-01 11:35:25 UTC
set cpu.max to "1000 10000" will also produce similar error since in src/util/virstring.c line539  "err = (errno || (!end_ptr && *p) || p == s);" the (!end_ptr && *p) will be true.

Comment 4 yisun 2019-09-17 12:04:14 UTC
PASSED in auto test job with libvirt-5.6.0-5.module+el8.1.0+4229+2e4e348c.x86_64:
https://libvirt-jenkins.rhev-ci-vms.eng.rdu2.redhat.com/job/libvirt-RHEL-8.1-runtest-x86_64-function-guest_resource_control/10/testReport/
(the single failed case is a script issue, not related to this bz)

Comment 6 errata-xmlrpc 2019-11-06 07:18:12 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2019:3723