Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions qemu/tests/cfg/virtio_fs_rlimit_nofile.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
- virtio_fs_rlimit_nofile:
no RHEL.6 RHEL.7 RHEL.8.0 RHEL.8.1
no Host_RHEL.m6 Host_RHEL.m7 Host_RHEL.m8.u0 Host_RHEL.m8.u1
type = virtio_fs_rlimit_nofile
required_virtiofsd_version = [1.13.2-1,)
virtiofsd_version_cmd = rpm -q virtiofsd | cut -d- -f2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Version check may under-report: include release in rpm query

cut -d- -f2 returns only VERSION (e.g., 1.13.2), but required_virtiofsd_version = [1.13.2-1,) expects VERSION-RELEASE. Use rpm queryformat.

Apply:

-    virtiofsd_version_cmd = rpm -q virtiofsd | cut -d- -f2
+    virtiofsd_version_cmd = rpm -q --qf '%{VERSION}-%{RELEASE}\n' virtiofsd
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
virtiofsd_version_cmd = rpm -q virtiofsd | cut -d- -f2
virtiofsd_version_cmd = rpm -q --qf '%{VERSION}-%{RELEASE}\n' virtiofsd
🤖 Prompt for AI Agents
In qemu/tests/cfg/virtio_fs_rlimit_nofile.cfg around line 7, the rpm query uses
`cut -d- -f2` which returns only VERSION and omits RELEASE, causing
under-reporting against a required VERSION-RELEASE range; update the command to
use rpm's queryformat to emit both version and release (e.g. use rpm -q --qf
'%{VERSION}-%{RELEASE}\n' virtiofsd) so the produced value matches the
required_virtiofsd_version format.

Win10.i386:
mem = 4096
fs_source_dir = /var/tmp/virtiofs_rlimit_nofile
force_create_fs_source = no
remove_fs_source = yes

pre_command = "mkdir -p ${fs_source_dir} && cd ${fs_source_dir}"
pre_command += " && for i in $(seq 1 1024); do touch file_$i.txt; done"
virtiofs_socket_path = '/var/tmp/virtiofs_rlimit_nofile.sock'
cmd_run_virtiofsd = '/usr/libexec/virtiofsd --socket-path ${virtiofs_socket_path} --shared-dir ${fs_source_dir}'

vm_mem_share = yes
vm_mem_backend = memory-backend-file
vm_mem_backend_path = /dev/shm
share_mem = yes
!s390, s390x:
mem_devs = mem1
backend_mem_mem1 = memory-backend-file
mem-path_mem1 = /dev/shm
size_mem1 = ${mem}M
use_mem_mem1 = no
guest_numa_nodes = shm0
numa_memdev_shm0 = mem-mem1
numa_nodeid_shm0 = 0
Windows:
# install winfsp tool
i386, i686:
install_winfsp_path = 'C:\Program Files'
devcon_dirname = 'x86'
x86_64:
install_winfsp_path = 'C:\Program Files (x86)'
devcon_dirname = 'amd64'
install_winfsp_cmd = 'msiexec /i WIN_UTILS:\winfsp.msi /qn'
check_installed_cmd = 'dir "%s" |findstr /I winfsp'
viofs_log_file = C:\viofs_log.txt
viofs_svc_name = VirtioFsSvc
viofs_exe_path = C:\virtiofs.exe
viofs_exe_copy_cmd = xcopy %s C:\ /Y
viofs_sc_create_cmd = 'sc create ${viofs_svc_name} binpath=${viofs_exe_path} start=auto'
viofs_sc_create_cmd += ' depend="WinFsp.Launcher/VirtioFsDrv" DisplayName="Virtio FS Service"'
viofs_sc_start_cmd = 'sc start ${viofs_svc_name}'
viofs_sc_query_cmd = 'sc query ${viofs_svc_name}'
viofs_sc_delete_cmd = 'sc delete ${viofs_svc_name}'
debug_log_operation = 'enable'
viofs_debug_enable_cmd = 'reg add HKLM\Software\VirtIO-FS /v DebugFlags /d 0xFFFFFFFF /t REG_DWORD'
viofs_log_enable_cmd = 'reg add HKLM\Software\VirtIO-FS /v DebugLogFile /d ${viofs_log_file} /t REG_SZ'
viofs_debug_delete_cmd = 'reg delete HKLM\Software\VirtIO-FS /v DebugFlags /f'
viofs_log_delete_cmd = 'reg delete HKLM\Software\VirtIO-FS /v DebugLogFile /f'
viofs_reg_query_cmd = 'reg query HKLM\Software\VirtIO-FS'
virtio_win_media_type = iso
cdroms += " virtio"
variants:
- rlimit_nofile_512:
start_vm = no
rlimit_nofile = 512
cmd_run_virtiofsd += " --rlimit-nofile ${rlimit_nofile}"
expected_msg = "Maximum number of file descriptors too small: Limit is 512, must be at least 610"
- rlimit_nofile_610:
start_vm = no
rlimit_nofile = 610
cmd_run_virtiofsd += " --rlimit-nofile ${rlimit_nofile}"
expected_msg = "File descriptor count limit is very small, leaving only 0 file descriptors for the guest"
- rlimit_nofile_1000:
kill_vm = yes
start_vm = yes
filesystems = fs
fs_driver = virtio-fs
fs_source_type = mount
fs_target = 'myfs'
fs_driver_props = {"queue-size": 1024}
fs_dest = '/mnt/${fs_target}'
driver_name = viofs
rlimit_nofile = 1000
fs_binary_extra_options += " --rlimit-nofile ${rlimit_nofile}"
list_file_cmd = "ls -c %s"
ls_check_content = "Too many open files in system"
Windows:
list_file_cmd = "dir %s"
ls_check_content = "388 File(s)"
- rlimit_nofile_2048:
kill_vm = yes
start_vm = yes
filesystems = fs
fs_driver = virtio-fs
fs_source_type = mount
fs_target = 'myfs'
fs_driver_props = {"queue-size": 1024}
fs_dest = '/mnt/${fs_target}'
driver_name = viofs
rlimit_nofile = 2048
fs_binary_extra_options += " --rlimit-nofile ${rlimit_nofile}"
list_file_cmd = "ls %s"
Windows:
list_file_cmd = "dir %s"
185 changes: 185 additions & 0 deletions qemu/tests/virtio_fs_rlimit_nofile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import aexpect
from avocado.utils import process
from virttest import error_context, utils_disk, utils_misc, utils_test

from provider import virtio_fs_utils


@error_context.context_aware
def run(test, params, env):
"""
Test virtio-fs rlimit-nofile.
Steps:
1. Create a shared directory for testing on the host.
2. Touch 1024 files in the shared directory.
3. Start the virtiofsd daemon with rlimit-nofile and check.

:param test: QEMU test object.
:param params: Dictionary with the test parameters.
:param env: Dictionary with test environment.
"""

def create_service(session):
if os_type == "windows":
error_context.context("Create virtiofs service in guest.", test.log.info)

driver_name = params["driver_name"]

session = utils_test.qemu.windrv_check_running_verifier(
session, vm, test, driver_name
)
viofs_svc_name = params["viofs_svc_name"]
virtio_fs_utils.create_viofs_service(
test, params, session, service=viofs_svc_name
)
return session

def delete_service():
if os_type == "windows":
error_context.context("Delete virtiofs service in guest.", test.log.info)
session = vm.wait_for_login()
virtio_fs_utils.delete_viofs_serivce(test, params, session)
session.close()

def start_service(session):
fs = params["filesystems"]
fs_params = params.object_params(fs)
Comment on lines +45 to +46
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Guard against missing filesystems parameter.

Lines 45-46 fetch filesystems from params without error handling. If this parameter is missing or misconfigured, the test will crash with an unhelpful KeyError instead of providing clear context.

Add defensive handling:

     def start_service(session):
-        fs = params["filesystems"]
+        fs = params.get("filesystems")
+        if not fs:
+            test.error("filesystems parameter is required but not found in config")
         fs_params = params.object_params(fs)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fs = params["filesystems"]
fs_params = params.object_params(fs)
def start_service(session):
fs = params.get("filesystems")
if not fs:
test.error("filesystems parameter is required but not found in config")
fs_params = params.object_params(fs)
🤖 Prompt for AI Agents
In qemu/tests/virtio_fs_rlimit_nofile.py around lines 45-46, the code directly
accesses params["filesystems"] which raises an unhelpful KeyError if the
parameter is missing; update this to defensively handle missing or misconfigured
input by first checking for the key (e.g., use params.get("filesystems") or a
try/except KeyError), and if absent log or raise a clear, contextual error
message (or skip the test) explaining that the 'filesystems' parameter is
required; then only call params.object_params(fs) when a valid fs value is
present.


fs_target = fs_params["fs_target"]
fs_dest = fs_params["fs_dest"]

if os_type == "linux":
utils_misc.make_dirs(fs_dest, session)
error_context.context(
"Mount virtiofs target %s to %s inside guest." % (fs_target, fs_dest),
test.log.info,
)
if not utils_disk.mount(fs_target, fs_dest, "virtiofs", session=session):
utils_misc.safe_rmdir(fs_dest, session=session)
test.fail("Failed to mount virtiofs %s." % fs_target)
else:
error_context.context("Start virtiofs service in guest.", test.log.info)
debug_log_operation = params.get("debug_log_operation")
if debug_log_operation:
session = virtio_fs_utils.operate_debug_log(
test, params, session, vm, debug_log_operation
)
virtio_fs_utils.start_viofs_service(test, params, session)

fs_dest = "%s:" % virtio_fs_utils.get_virtiofs_driver_letter(
test, fs_target, session
)

guest_mnts[fs_target] = fs_dest
return session

def stop_service(session):
error_context.context("Stop virtiofs service in guest.", test.log.info)

if os_type == "linux":
for fs_target, fs_dest in guest_mnts.items():
utils_disk.umount(fs_target, fs_dest, "virtiofs", session=session)
utils_misc.safe_rmdir(fs_dest, session=session)
else:
if guest_mnts:
virtio_fs_utils.stop_viofs_service(test, params, session)
session.close()

rlimit_nofile = params.get("rlimit_nofile")
cmd_run_virtiofsd = params["cmd_run_virtiofsd"]
guest_mnts = dict()
os_type = params["os_type"]

if rlimit_nofile == "512":
expected_msg = params["expected_msg"]
error_context.context(
"Starting virtiofsd with rlimit-nofile=%s" % rlimit_nofile, test.log.info
)
result = process.run(
cmd_run_virtiofsd,
shell=True,
ignore_status=True,
verbose=True,
)
# Prefer text-safe access for command output (stderr for failure path)
status = result.exit_status
err_out = getattr(result, "stderr_text", None)
if err_out is None:
raw_err = getattr(result, "stderr", b"")
err_out = (
raw_err.decode()
if isinstance(raw_err, (bytes, bytearray))
else str(raw_err)
)
if status == 0:
test.fail(
"virtiofsd unexpectedly started successfully with rlimit-nofile=512"
)
elif expected_msg not in err_out:
test.fail(
"virtiofsd failed but without expected message. Output: %s" % err_out
)
error_context.context(
"virtiofsd failed as expected with the required message present",
test.log.info,
)
elif rlimit_nofile == "610":
expected_msg = params["expected_msg"]
error_context.context(
"Starting virtiofsd with rlimit-nofile=%s" % rlimit_nofile, test.log.info
)
session = aexpect.ShellSession(
cmd_run_virtiofsd,
auto_close=False,
output_func=utils_misc.log_line,
output_params=("virtiofs_fs-virtiofs.log",),
prompt=r"^\[.*\][\#\$]\s*$",
)
try:
session.read_until_any_line_matches([expected_msg], timeout=10)
test.log.info(
"virtiofsd started successfully with the required message present"
)
except aexpect.ExpectTimeoutError as e:
test.fail("Timeout for virtiofsd start with rlimit-nofile=610: %s" % e)
finally:
session.close()
elif rlimit_nofile == "1000":
error_context.context(
"Starting virtiofsd with rlimit-nofile=%s" % rlimit_nofile, test.log.info
)
vm = env.get_vm(params.get("main_vm"))
vm.verify_alive()
session = vm.wait_for_login()
try:
session = create_service(session)
session = start_service(session)
for fs_dest in guest_mnts.values():
# ls the dir in guest
out = session.cmd_output(params["list_file_cmd"] % fs_dest).strip()
test.log.debug("The dir output in guest: %s", out)
# check the qemu log whether there is the proper information
if params.get("ls_check_content") not in out:
test.fail("The list output is not proper: %s" % out)
finally:
stop_service(session)
delete_service()
elif rlimit_nofile == "2048":
error_context.context(
"Starting virtiofsd with rlimit-nofile=%s" % rlimit_nofile, test.log.info
)
vm = env.get_vm(params.get("main_vm"))
vm.verify_alive()
session = vm.wait_for_login()
try:
session = create_service(session)
session = start_service(session)
for fs_dest in guest_mnts.values():
cmd = params["list_file_cmd"] % fs_dest
status, output = session.cmd_status_output(cmd)
output = output.strip()
if status != 0:
test.fail("list failed: %s" % output)
finally:
stop_service(session)
delete_service()