16e1b58faSStephen Hemminger#! /usr/bin/env python3 26e1b58faSStephen Hemminger# SPDX-License-Identifier: BSD-3-Clause 36e1b58faSStephen Hemminger# Copyright (c) 2020 Microsoft Corporation 4*f63ca249SAnatoly Burakov 56e1b58faSStephen Hemminger"""Script to query and setup huge pages for DPDK applications.""" 66e1b58faSStephen Hemminger 76e1b58faSStephen Hemmingerimport argparse 86e1b58faSStephen Hemmingerimport os 96e1b58faSStephen Hemmingerimport re 10*f63ca249SAnatoly Burakovimport subprocess 116e1b58faSStephen Hemmingerimport sys 12*f63ca249SAnatoly Burakovimport typing as T 136e1b58faSStephen Hemmingerfrom math import log2 146e1b58faSStephen Hemminger 156e1b58faSStephen Hemminger# Standard binary prefix 166e1b58faSStephen HemmingerBINARY_PREFIX = "KMG" 176e1b58faSStephen Hemminger 186e1b58faSStephen Hemminger# systemd mount point for huge pages 196e1b58faSStephen HemmingerHUGE_MOUNT = "/dev/hugepages" 20*f63ca249SAnatoly Burakov# default directory for non-NUMA huge pages 21*f63ca249SAnatoly BurakovNO_NUMA_HUGE_DIR = "/sys/kernel/mm/hugepages" 22*f63ca249SAnatoly Burakov# default base directory for NUMA nodes 23*f63ca249SAnatoly BurakovNUMA_NODE_BASE_DIR = "/sys/devices/system/node" 24*f63ca249SAnatoly Burakov# procfs paths 25*f63ca249SAnatoly BurakovMEMINFO_PATH = "/proc/meminfo" 26*f63ca249SAnatoly BurakovMOUNTS_PATH = "/proc/mounts" 276e1b58faSStephen Hemminger 286e1b58faSStephen Hemminger 29*f63ca249SAnatoly Burakovclass HugepageMount: 30*f63ca249SAnatoly Burakov """Mount operations for huge page filesystem.""" 31*f63ca249SAnatoly Burakov 32*f63ca249SAnatoly Burakov def __init__(self, path: str, mounted: bool): 33*f63ca249SAnatoly Burakov self.path = path 34*f63ca249SAnatoly Burakov # current mount status 35*f63ca249SAnatoly Burakov self.mounted = mounted 36*f63ca249SAnatoly Burakov 37*f63ca249SAnatoly Burakov def mount( 38*f63ca249SAnatoly Burakov self, pagesize_kb: int, user: T.Optional[str], group: T.Optional[str] 39*f63ca249SAnatoly Burakov ) -> None: 40*f63ca249SAnatoly Burakov """Mount the huge TLB file system""" 41*f63ca249SAnatoly Burakov if self.mounted: 42*f63ca249SAnatoly Burakov return 43*f63ca249SAnatoly Burakov cmd = ["mount", "-t", "hugetlbfs"] 44*f63ca249SAnatoly Burakov cmd += ["-o", f"pagesize={pagesize_kb * 1024}"] 45*f63ca249SAnatoly Burakov if user is not None: 46*f63ca249SAnatoly Burakov cmd += ["-o", f"uid={user}"] 47*f63ca249SAnatoly Burakov if group is not None: 48*f63ca249SAnatoly Burakov cmd += ["-o", f"gid={group}"] 49*f63ca249SAnatoly Burakov cmd += ["nodev", self.path] 50*f63ca249SAnatoly Burakov 51*f63ca249SAnatoly Burakov subprocess.run(cmd, check=True) 52*f63ca249SAnatoly Burakov self.mounted = True 53*f63ca249SAnatoly Burakov 54*f63ca249SAnatoly Burakov def unmount(self) -> None: 55*f63ca249SAnatoly Burakov """Unmount the huge TLB file system (if mounted)""" 56*f63ca249SAnatoly Burakov if self.mounted: 57*f63ca249SAnatoly Burakov subprocess.run(["umount", self.path], check=True) 58*f63ca249SAnatoly Burakov self.mounted = False 59*f63ca249SAnatoly Burakov 60*f63ca249SAnatoly Burakov 61*f63ca249SAnatoly Burakovclass HugepageRes: 62*f63ca249SAnatoly Burakov """Huge page reserve operations. Can be NUMA-node-specific.""" 63*f63ca249SAnatoly Burakov 64*f63ca249SAnatoly Burakov def __init__(self, path: str, node: T.Optional[int] = None): 65*f63ca249SAnatoly Burakov self.path = path 66*f63ca249SAnatoly Burakov # if this is a per-NUMA node huge page dir, store the node number 67*f63ca249SAnatoly Burakov self.node = node 68*f63ca249SAnatoly Burakov self.valid_page_sizes = self._get_valid_page_sizes() 69*f63ca249SAnatoly Burakov 70*f63ca249SAnatoly Burakov def _get_valid_page_sizes(self) -> T.List[int]: 71*f63ca249SAnatoly Burakov """Extract valid huge page sizes""" 72*f63ca249SAnatoly Burakov return [get_memsize(d.split("-")[1]) for d in os.listdir(self.path)] 73*f63ca249SAnatoly Burakov 74*f63ca249SAnatoly Burakov def _nr_pages_path(self, sz: int) -> str: 75*f63ca249SAnatoly Burakov if sz not in self.valid_page_sizes: 76*f63ca249SAnatoly Burakov raise ValueError( 77*f63ca249SAnatoly Burakov f"Invalid page size {sz}. " f"Valid sizes: {self.valid_page_sizes}" 78*f63ca249SAnatoly Burakov ) 79*f63ca249SAnatoly Burakov return os.path.join(self.path, f"hugepages-{sz}kB", "nr_hugepages") 80*f63ca249SAnatoly Burakov 81*f63ca249SAnatoly Burakov def __getitem__(self, sz: int) -> int: 82*f63ca249SAnatoly Burakov """Get current number of reserved pages of specified size""" 83*f63ca249SAnatoly Burakov with open(self._nr_pages_path(sz), encoding="utf-8") as f: 84*f63ca249SAnatoly Burakov return int(f.read()) 85*f63ca249SAnatoly Burakov 86*f63ca249SAnatoly Burakov def __setitem__(self, sz: int, nr_pages: int) -> None: 87*f63ca249SAnatoly Burakov """Set number of reserved pages of specified size""" 88*f63ca249SAnatoly Burakov with open(self._nr_pages_path(sz), "w", encoding="utf-8") as f: 89*f63ca249SAnatoly Burakov f.write(f"{nr_pages}\n") 90*f63ca249SAnatoly Burakov 91*f63ca249SAnatoly Burakov 92*f63ca249SAnatoly Burakovdef fmt_memsize(kb: int) -> str: 93*f63ca249SAnatoly Burakov """Format memory size in kB into conventional format""" 946e1b58faSStephen Hemminger logk = int(log2(kb) / 10) 956e1b58faSStephen Hemminger suffix = BINARY_PREFIX[logk] 966e1b58faSStephen Hemminger unit = 2 ** (logk * 10) 97*f63ca249SAnatoly Burakov return f"{int(kb / unit)}{suffix}b" 986e1b58faSStephen Hemminger 996e1b58faSStephen Hemminger 100*f63ca249SAnatoly Burakovdef get_memsize(arg: str) -> int: 101*f63ca249SAnatoly Burakov """Convert memory size with suffix to kB""" 102*f63ca249SAnatoly Burakov # arg may have a 'b' at the end 103*f63ca249SAnatoly Burakov if arg[-1].lower() == "b": 104*f63ca249SAnatoly Burakov arg = arg[:-1] 105*f63ca249SAnatoly Burakov match = re.match(rf"(\d+)([{BINARY_PREFIX}]?)$", arg.upper()) 1066e1b58faSStephen Hemminger if match is None: 107*f63ca249SAnatoly Burakov raise ValueError(f"{arg} is not a valid size") 1086e1b58faSStephen Hemminger num = float(match.group(1)) 1096e1b58faSStephen Hemminger suffix = match.group(2) 110*f63ca249SAnatoly Burakov if not suffix: 1116e1b58faSStephen Hemminger return int(num / 1024) 1126e1b58faSStephen Hemminger idx = BINARY_PREFIX.find(suffix) 1136e1b58faSStephen Hemminger return int(num * (2 ** (idx * 10))) 1146e1b58faSStephen Hemminger 1156e1b58faSStephen Hemminger 116*f63ca249SAnatoly Burakovdef is_numa() -> bool: 117*f63ca249SAnatoly Burakov """Check if NUMA is supported""" 118*f63ca249SAnatoly Burakov return os.path.exists(NUMA_NODE_BASE_DIR) 1196e1b58faSStephen Hemminger 1206e1b58faSStephen Hemminger 121*f63ca249SAnatoly Burakovdef default_pagesize() -> int: 122*f63ca249SAnatoly Burakov """Get default huge page size from /proc/meminfo""" 123*f63ca249SAnatoly Burakov key = "Hugepagesize" 124*f63ca249SAnatoly Burakov with open(MEMINFO_PATH, encoding="utf-8") as meminfo: 1256e1b58faSStephen Hemminger for line in meminfo: 126*f63ca249SAnatoly Burakov if line.startswith(f"{key}:"): 1276e1b58faSStephen Hemminger return int(line.split()[1]) 128*f63ca249SAnatoly Burakov raise KeyError(f'"{key}" not found in {MEMINFO_PATH}') 1296e1b58faSStephen Hemminger 1306e1b58faSStephen Hemminger 131*f63ca249SAnatoly Burakovdef get_hugetlbfs_mountpoints() -> T.List[str]: 132*f63ca249SAnatoly Burakov """Get list of where huge page filesystem is mounted""" 133*f63ca249SAnatoly Burakov mounted: T.List[str] = [] 134*f63ca249SAnatoly Burakov with open(MOUNTS_PATH, encoding="utf-8") as mounts: 1356e1b58faSStephen Hemminger for line in mounts: 1366e1b58faSStephen Hemminger fields = line.split() 137*f63ca249SAnatoly Burakov if fields[2] != "hugetlbfs": 1386e1b58faSStephen Hemminger continue 1396e1b58faSStephen Hemminger mounted.append(fields[1]) 1406e1b58faSStephen Hemminger return mounted 1416e1b58faSStephen Hemminger 1426e1b58faSStephen Hemminger 143*f63ca249SAnatoly Burakovdef print_row(cells: T.Tuple[str, ...], widths: T.List[int]) -> None: 144*f63ca249SAnatoly Burakov """Print a row of a table with the given column widths""" 145*f63ca249SAnatoly Burakov first, *rest = cells 146*f63ca249SAnatoly Burakov w_first, *w_rest = widths 147*f63ca249SAnatoly Burakov first_end = " " * 2 148*f63ca249SAnatoly Burakov rest_end = " " * 2 149*f63ca249SAnatoly Burakov 150*f63ca249SAnatoly Burakov print(first.ljust(w_first), end=first_end) 151*f63ca249SAnatoly Burakov for cell, width in zip(rest, w_rest): 152*f63ca249SAnatoly Burakov print(cell.rjust(width), end=rest_end) 153*f63ca249SAnatoly Burakov print() 1546e1b58faSStephen Hemminger 1556e1b58faSStephen Hemminger 156*f63ca249SAnatoly Burakovdef print_hp_status(hp_res: T.List[HugepageRes]) -> None: 157*f63ca249SAnatoly Burakov """Display status of huge page reservations""" 158*f63ca249SAnatoly Burakov numa = is_numa() 1596e1b58faSStephen Hemminger 160*f63ca249SAnatoly Burakov # print out huge page information in a table 161*f63ca249SAnatoly Burakov rows: T.List[T.Tuple[str, ...]] 162*f63ca249SAnatoly Burakov headers: T.Tuple[str, ...] 163*f63ca249SAnatoly Burakov if numa: 164*f63ca249SAnatoly Burakov headers = "Node", "Pages", "Size", "Total" 165*f63ca249SAnatoly Burakov rows = [ 166*f63ca249SAnatoly Burakov ( 167*f63ca249SAnatoly Burakov str(hp.node), 168*f63ca249SAnatoly Burakov str(nr_pages), 169*f63ca249SAnatoly Burakov fmt_memsize(sz), 170*f63ca249SAnatoly Burakov fmt_memsize(sz * nr_pages), 171*f63ca249SAnatoly Burakov ) 172*f63ca249SAnatoly Burakov # iterate over each huge page sysfs node... 173*f63ca249SAnatoly Burakov for hp in hp_res 174*f63ca249SAnatoly Burakov # ...and each page size within that node... 175*f63ca249SAnatoly Burakov for sz in hp.valid_page_sizes 176*f63ca249SAnatoly Burakov # ...we need number of pages multiple times, so we read it here... 177*f63ca249SAnatoly Burakov for nr_pages in [hp[sz]] 178*f63ca249SAnatoly Burakov # ...include this row only if there are pages reserved 179*f63ca249SAnatoly Burakov if nr_pages 180*f63ca249SAnatoly Burakov ] 1816e1b58faSStephen Hemminger else: 182*f63ca249SAnatoly Burakov headers = "Pages", "Size", "Total" 183*f63ca249SAnatoly Burakov # if NUMA is disabled, we know there's only one huge page dir 184*f63ca249SAnatoly Burakov hp = hp_res[0] 185*f63ca249SAnatoly Burakov rows = [ 186*f63ca249SAnatoly Burakov (str(nr_pages), fmt_memsize(sz), fmt_memsize(sz * nr_pages)) 187*f63ca249SAnatoly Burakov # iterate over each page size within the huge page dir 188*f63ca249SAnatoly Burakov for sz in hp.valid_page_sizes 189*f63ca249SAnatoly Burakov # read number of pages for this size 190*f63ca249SAnatoly Burakov for nr_pages in [hp[sz]] 191*f63ca249SAnatoly Burakov # skip if no pages 192*f63ca249SAnatoly Burakov if nr_pages 193*f63ca249SAnatoly Burakov ] 194*f63ca249SAnatoly Burakov if not rows: 195*f63ca249SAnatoly Burakov print("No huge pages reserved") 196*f63ca249SAnatoly Burakov return 197*f63ca249SAnatoly Burakov 198*f63ca249SAnatoly Burakov # find max widths for each column, including header and rows 199*f63ca249SAnatoly Burakov col_widths = [ 200*f63ca249SAnatoly Burakov max(len(tup[col_idx]) for tup in rows + [headers]) 201*f63ca249SAnatoly Burakov for col_idx in range(len(headers)) 202*f63ca249SAnatoly Burakov ] 203*f63ca249SAnatoly Burakov 204*f63ca249SAnatoly Burakov # print everything 205*f63ca249SAnatoly Burakov print_row(headers, col_widths) 206*f63ca249SAnatoly Burakov for r in rows: 207*f63ca249SAnatoly Burakov print_row(r, col_widths) 208*f63ca249SAnatoly Burakov 209*f63ca249SAnatoly Burakov 210*f63ca249SAnatoly Burakovdef print_mount_status() -> None: 211*f63ca249SAnatoly Burakov """Display status of huge page filesystem mounts""" 212*f63ca249SAnatoly Burakov mounted = get_hugetlbfs_mountpoints() 213*f63ca249SAnatoly Burakov if not mounted: 214*f63ca249SAnatoly Burakov print("No huge page filesystems mounted") 215*f63ca249SAnatoly Burakov return 216*f63ca249SAnatoly Burakov print("Huge page filesystems mounted at:", *mounted, sep=" ") 217*f63ca249SAnatoly Burakov 218*f63ca249SAnatoly Burakov 219*f63ca249SAnatoly Burakovdef scan_huge_dirs(node: T.Optional[int]) -> T.List[HugepageRes]: 220*f63ca249SAnatoly Burakov """Return a HugepageRes object for each huge page directory""" 221*f63ca249SAnatoly Burakov # if NUMA is enabled, scan per-NUMA node huge pages 222*f63ca249SAnatoly Burakov if is_numa(): 223*f63ca249SAnatoly Burakov # helper function to extract node number from directory name 224*f63ca249SAnatoly Burakov def _get_node(path: str) -> T.Optional[int]: 225*f63ca249SAnatoly Burakov m = re.match(r"node(\d+)", os.path.basename(path)) 226*f63ca249SAnatoly Burakov return int(m.group(1)) if m else None 227*f63ca249SAnatoly Burakov 228*f63ca249SAnatoly Burakov # we want a sorted list of NUMA nodes 229*f63ca249SAnatoly Burakov nodes = sorted( 230*f63ca249SAnatoly Burakov n 231*f63ca249SAnatoly Burakov # iterate over all directories in the base directory 232*f63ca249SAnatoly Burakov for d in os.listdir(NUMA_NODE_BASE_DIR) 233*f63ca249SAnatoly Burakov # extract the node number from the directory name 234*f63ca249SAnatoly Burakov for n in [_get_node(d)] 235*f63ca249SAnatoly Burakov # filter out None values (non-NUMA node directories) 236*f63ca249SAnatoly Burakov if n is not None 237*f63ca249SAnatoly Burakov ) 238*f63ca249SAnatoly Burakov return [ 239*f63ca249SAnatoly Burakov HugepageRes(os.path.join(NUMA_NODE_BASE_DIR, f"node{n}", "hugepages"), n) 240*f63ca249SAnatoly Burakov for n in nodes 241*f63ca249SAnatoly Burakov # if user requested a specific node, only include that one 242*f63ca249SAnatoly Burakov if node is None or n == node 243*f63ca249SAnatoly Burakov ] 244*f63ca249SAnatoly Burakov # otherwise, use non-NUMA huge page directory 245*f63ca249SAnatoly Burakov if node is not None: 246*f63ca249SAnatoly Burakov raise ValueError("NUMA node requested but not supported") 247*f63ca249SAnatoly Burakov return [HugepageRes(NO_NUMA_HUGE_DIR)] 248*f63ca249SAnatoly Burakov 249*f63ca249SAnatoly Burakov 250*f63ca249SAnatoly Burakovdef try_reserve_huge_pages( 251*f63ca249SAnatoly Burakov hp_res: T.List[HugepageRes], mem_sz: str, pagesize_kb: int 252*f63ca249SAnatoly Burakov) -> None: 253*f63ca249SAnatoly Burakov """Reserve huge pages if possible""" 254*f63ca249SAnatoly Burakov reserve_kb = get_memsize(mem_sz) 255*f63ca249SAnatoly Burakov 256*f63ca249SAnatoly Burakov # is this a valid request? 257*f63ca249SAnatoly Burakov if reserve_kb % pagesize_kb != 0: 258*f63ca249SAnatoly Burakov fmt_res = fmt_memsize(reserve_kb) 259*f63ca249SAnatoly Burakov fmt_sz = fmt_memsize(pagesize_kb) 260*f63ca249SAnatoly Burakov raise ValueError( 261*f63ca249SAnatoly Burakov f"Huge reservation {fmt_res} is " f"not a multiple of page size {fmt_sz}" 262*f63ca249SAnatoly Burakov ) 263*f63ca249SAnatoly Burakov 264*f63ca249SAnatoly Burakov # request is valid, reserve pages 265*f63ca249SAnatoly Burakov for hp in hp_res: 266*f63ca249SAnatoly Burakov req = reserve_kb // pagesize_kb 267*f63ca249SAnatoly Burakov hp[pagesize_kb] = req 268*f63ca249SAnatoly Burakov got = hp[pagesize_kb] 269*f63ca249SAnatoly Burakov # did we fulfill our request? 270*f63ca249SAnatoly Burakov if got != req: 271*f63ca249SAnatoly Burakov raise OSError( 272*f63ca249SAnatoly Burakov f"Failed to reserve {req} pages of size " 273*f63ca249SAnatoly Burakov f"{fmt_memsize(pagesize_kb)}, " 274*f63ca249SAnatoly Burakov f"got {got} pages instead" 275*f63ca249SAnatoly Burakov ) 2766e1b58faSStephen Hemminger 2776e1b58faSStephen Hemminger 2786e1b58faSStephen Hemmingerdef main(): 279*f63ca249SAnatoly Burakov """Process the command line arguments and setup huge pages""" 2806e1b58faSStephen Hemminger parser = argparse.ArgumentParser( 2816e1b58faSStephen Hemminger formatter_class=argparse.RawDescriptionHelpFormatter, 2826e1b58faSStephen Hemminger description="Setup huge pages", 2836e1b58faSStephen Hemminger epilog=""" 2846e1b58faSStephen HemmingerExamples: 2856e1b58faSStephen Hemminger 2866e1b58faSStephen HemmingerTo display current huge page settings: 2876e1b58faSStephen Hemminger %(prog)s -s 2886e1b58faSStephen Hemminger 2896e1b58faSStephen HemmingerTo a complete setup of with 2 Gigabyte of 1G huge pages: 2906e1b58faSStephen Hemminger %(prog)s -p 1G --setup 2G 291*f63ca249SAnatoly Burakov""", 292*f63ca249SAnatoly Burakov ) 2936e1b58faSStephen Hemminger parser.add_argument( 294*f63ca249SAnatoly Burakov "--show", 295*f63ca249SAnatoly Burakov "-s", 296*f63ca249SAnatoly Burakov action="store_true", 297*f63ca249SAnatoly Burakov help="Print current huge page configuration", 298*f63ca249SAnatoly Burakov ) 2996e1b58faSStephen Hemminger parser.add_argument( 300*f63ca249SAnatoly Burakov "--clear", "-c", action="store_true", help="Clear existing huge pages" 301*f63ca249SAnatoly Burakov ) 3026e1b58faSStephen Hemminger parser.add_argument( 303*f63ca249SAnatoly Burakov "--mount", 304*f63ca249SAnatoly Burakov "-m", 305*f63ca249SAnatoly Burakov action="store_true", 306*f63ca249SAnatoly Burakov help="Mount the huge page filesystem", 307*f63ca249SAnatoly Burakov ) 3086e1b58faSStephen Hemminger parser.add_argument( 309*f63ca249SAnatoly Burakov "--unmount", 310*f63ca249SAnatoly Burakov "-u", 311*f63ca249SAnatoly Burakov action="store_true", 312*f63ca249SAnatoly Burakov help="Unmount the system huge page directory", 313*f63ca249SAnatoly Burakov ) 3146e1b58faSStephen Hemminger parser.add_argument( 315*f63ca249SAnatoly Burakov "--directory", 316*f63ca249SAnatoly Burakov "-d", 317*f63ca249SAnatoly Burakov metavar="DIR", 31831af02efSDmitry Kozlyuk default=HUGE_MOUNT, 319*f63ca249SAnatoly Burakov help="Mount point for huge pages", 320*f63ca249SAnatoly Burakov ) 32131af02efSDmitry Kozlyuk parser.add_argument( 322*f63ca249SAnatoly Burakov "--user", 323*f63ca249SAnatoly Burakov "-U", 324*f63ca249SAnatoly Burakov metavar="UID", 325*f63ca249SAnatoly Burakov help="Set the mounted directory owner user", 326*f63ca249SAnatoly Burakov ) 3278d73de6fSDmitry Kozlyuk parser.add_argument( 328*f63ca249SAnatoly Burakov "--group", 329*f63ca249SAnatoly Burakov "-G", 330*f63ca249SAnatoly Burakov metavar="GID", 331*f63ca249SAnatoly Burakov help="Set the mounted directory owner group", 332*f63ca249SAnatoly Burakov ) 3338d73de6fSDmitry Kozlyuk parser.add_argument( 334*f63ca249SAnatoly Burakov "--node", "-n", type=int, help="Select numa node to reserve pages on" 335*f63ca249SAnatoly Burakov ) 3366e1b58faSStephen Hemminger parser.add_argument( 337*f63ca249SAnatoly Burakov "--pagesize", "-p", metavar="SIZE", help="Choose huge page size to use" 338*f63ca249SAnatoly Burakov ) 3396e1b58faSStephen Hemminger parser.add_argument( 340*f63ca249SAnatoly Burakov "--reserve", 341*f63ca249SAnatoly Burakov "-r", 342*f63ca249SAnatoly Burakov metavar="SIZE", 343*f63ca249SAnatoly Burakov help="Reserve huge pages. Size is in bytes with K, M, or G suffix", 344*f63ca249SAnatoly Burakov ) 3456e1b58faSStephen Hemminger parser.add_argument( 346*f63ca249SAnatoly Burakov "--setup", 347*f63ca249SAnatoly Burakov metavar="SIZE", 348*f63ca249SAnatoly Burakov help="Setup huge pages by doing clear, unmount, reserve and mount", 349*f63ca249SAnatoly Burakov ) 3506e1b58faSStephen Hemminger args = parser.parse_args() 3516e1b58faSStephen Hemminger 352*f63ca249SAnatoly Burakov # setup is clear, then unmount, then reserve, then mount 3536e1b58faSStephen Hemminger if args.setup: 3546e1b58faSStephen Hemminger args.clear = True 3556e1b58faSStephen Hemminger args.unmount = True 3566e1b58faSStephen Hemminger args.reserve = args.setup 3576e1b58faSStephen Hemminger args.mount = True 3586e1b58faSStephen Hemminger 359b41bd046SThomas Monjalon if not (args.show or args.mount or args.unmount or args.clear or args.reserve): 360b41bd046SThomas Monjalon parser.error("no action specified") 361b41bd046SThomas Monjalon 362*f63ca249SAnatoly Burakov # read huge page data from sysfs 363*f63ca249SAnatoly Burakov hp_res = scan_huge_dirs(args.node) 364*f63ca249SAnatoly Burakov 365*f63ca249SAnatoly Burakov # read huge page mountpoint data 366*f63ca249SAnatoly Burakov hp_mountpoint = args.directory 367*f63ca249SAnatoly Burakov hp_mounted = hp_mountpoint in get_hugetlbfs_mountpoints() 368*f63ca249SAnatoly Burakov hp_mount = HugepageMount(hp_mountpoint, hp_mounted) 369*f63ca249SAnatoly Burakov 370*f63ca249SAnatoly Burakov # get requested page size we will be working with 3716e1b58faSStephen Hemminger if args.pagesize: 3726e1b58faSStephen Hemminger pagesize_kb = get_memsize(args.pagesize) 3736e1b58faSStephen Hemminger else: 3746e1b58faSStephen Hemminger pagesize_kb = default_pagesize() 3756e1b58faSStephen Hemminger 376*f63ca249SAnatoly Burakov # were we asked to clear? 3776e1b58faSStephen Hemminger if args.clear: 378*f63ca249SAnatoly Burakov for hp in hp_res: 379*f63ca249SAnatoly Burakov for sz in hp.valid_page_sizes: 380*f63ca249SAnatoly Burakov hp[sz] = 0 3816e1b58faSStephen Hemminger 382*f63ca249SAnatoly Burakov # were we asked to unmount? 383*f63ca249SAnatoly Burakov if args.unmount: 384*f63ca249SAnatoly Burakov hp_mount.unmount() 385*f63ca249SAnatoly Burakov 386*f63ca249SAnatoly Burakov # were we asked to reserve pages? 3876e1b58faSStephen Hemminger if args.reserve: 388*f63ca249SAnatoly Burakov try_reserve_huge_pages(hp_res, args.reserve, pagesize_kb) 389*f63ca249SAnatoly Burakov 390*f63ca249SAnatoly Burakov # were we asked to mount? 3916e1b58faSStephen Hemminger if args.mount: 392*f63ca249SAnatoly Burakov hp_mount.mount(pagesize_kb, args.user, args.group) 393*f63ca249SAnatoly Burakov 394*f63ca249SAnatoly Burakov # were we asked to display status? 3956e1b58faSStephen Hemminger if args.show: 396*f63ca249SAnatoly Burakov print_hp_status(hp_res) 3976e1b58faSStephen Hemminger print() 398*f63ca249SAnatoly Burakov print_mount_status() 3996e1b58faSStephen Hemminger 4006e1b58faSStephen Hemminger 4016e1b58faSStephen Hemmingerif __name__ == "__main__": 402*f63ca249SAnatoly Burakov try: 4036e1b58faSStephen Hemminger main() 404*f63ca249SAnatoly Burakov except PermissionError: 405*f63ca249SAnatoly Burakov sys.exit("Permission denied: need to be root!") 406*f63ca249SAnatoly Burakov except subprocess.CalledProcessError as e: 407*f63ca249SAnatoly Burakov sys.exit(f"Command failed: {e}") 408*f63ca249SAnatoly Burakov except (KeyError, ValueError, OSError) as e: 409*f63ca249SAnatoly Burakov sys.exit(f"Error: {e}") 410