Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mtab check optional #1486

Closed
wants to merge 1 commit into from
Closed
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
63 changes: 33 additions & 30 deletions casadm/cas_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@

#define CORE_ADD_MAX_TIMEOUT 30

int is_cache_mounted(int cache_id);
int is_core_mounted(int cache_id, int core_id);
bool cache_mounts_detected(int cache_id);
bool core_mounts_detected(int cache_id, int core_id);

/* KCAS_IOCTL_CACHE_CHECK_DEVICE wrapper */
int _check_cache_device(const char *device_path,
Expand Down Expand Up @@ -1119,7 +1119,7 @@ int stop_cache(uint16_t cache_id, int flush)
int status;

/* Don't stop instance with mounted filesystem */
if (is_cache_mounted(cache_id) == FAILURE)
if (cache_mounts_detected(cache_id))
return FAILURE;

fd = open_ctrl_device();
Expand Down Expand Up @@ -1803,58 +1803,61 @@ int add_core(unsigned int cache_id, unsigned int core_id, const char *core_devic
return SUCCESS;
}

int _check_if_mounted(int cache_id, int core_id)
bool _device_mounts_detected(int cache_id, int core_id)
{
FILE *mtab;
struct mntent *mstruct;
char dev_buf[80];
int difference = 0, error = 0;
int no_match = 0, error = 0, cmplen = 0;
if (core_id >= 0) {
/* verify if specific core is mounted */
snprintf(dev_buf, sizeof(dev_buf), "/dev/cas%d-%d", cache_id, core_id);
cmplen = snprintf(dev_buf, sizeof(dev_buf), "/dev/cas%d-%d", cache_id, core_id);
} else {
/* verify if any core from given cache is mounted */
snprintf(dev_buf, sizeof(dev_buf), "/dev/cas%d-", cache_id);
/* verify if any core from given cache is mounted
do not compare terminating NULL for cache */
cmplen = snprintf(dev_buf, sizeof(dev_buf), "/dev/cas%d-", cache_id) - 1;
}

mtab = setmntent("/etc/mtab", "r");
if (!mtab)
{
cas_printf(LOG_ERR, "Error while accessing /etc/mtab\n");
return FAILURE;
/* if /etc/mtab not found then the kernel will check for mounts */
return false;
}

while ((mstruct = getmntent(mtab)) != NULL) {
error = strcmp_s(mstruct->mnt_fsname, PATH_MAX, dev_buf, &difference);
error = strcmp_s(mstruct->mnt_fsname, cmplen, dev_buf, &no_match);
/* mstruct->mnt_fsname is /dev/... block device path, not a mountpoint */
if (error != EOK)
return FAILURE;
if (!difference) {
if (core_id<0) {
cas_printf(LOG_ERR,
"Can't stop cache instance %d. Device %s is mounted!\n",
cache_id, mstruct->mnt_fsname);
} else {
cas_printf(LOG_ERR,
"Can't remove core %d from cache %d."
" Device %s is mounted!\n",
core_id, cache_id, mstruct->mnt_fsname);
return false;
if (no_match)
continue;

if (core_id < 0) {
cas_printf(LOG_ERR,
"Can't stop cache instance %d. Device %s is mounted!\n",
cache_id, mstruct->mnt_fsname);
} else {
cas_printf(LOG_ERR,
"Can't remove core %d from cache %d."
" Device %s is mounted!\n",
core_id, cache_id, mstruct->mnt_fsname);
}
Comment on lines +1837 to 1845
Copy link
Contributor

Choose a reason for hiding this comment

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

This function should only check whether cores are mounted. The error messages should be printed by the caller function

return FAILURE;
return true;
}
}
return SUCCESS;

return false;
}

int is_cache_mounted(int cache_id)
bool cache_mounts_detected(int cache_id)
{
return _check_if_mounted(cache_id, -1);
return _device_mounts_detected(cache_id, -1);
}

int is_core_mounted(int cache_id, int core_id)
bool core_mounts_detected(int cache_id, int core_id)
{
return _check_if_mounted(cache_id, core_id);
return _device_mounts_detected(cache_id, core_id);
}

int remove_core(unsigned int cache_id, unsigned int core_id,
Expand All @@ -1864,7 +1867,7 @@ int remove_core(unsigned int cache_id, unsigned int core_id,
struct kcas_remove_core cmd;

/* don't even attempt ioctl if filesystem is mounted */
if (SUCCESS != is_core_mounted(cache_id, core_id)) {
if (core_mounts_detected(cache_id, core_id)) {
return FAILURE;
}

Expand Down Expand Up @@ -1930,7 +1933,7 @@ int remove_inactive_core(unsigned int cache_id, unsigned int core_id,
struct kcas_remove_inactive cmd;

/* don't even attempt ioctl if filesystem is mounted */
if (SUCCESS != is_core_mounted(cache_id, core_id)) {
if (core_mounts_detected(cache_id, core_id)) {
return FAILURE;
}

Expand Down
12 changes: 11 additions & 1 deletion test/functional/api/cas/cli_messages.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#
# Copyright(c) 2019-2022 Intel Corporation
# Copyright(c) 2024 Huawei Technologies
# SPDX-License-Identifier: BSD-3-Clause
#

Expand Down Expand Up @@ -92,8 +93,17 @@
r"Can\'t remove core \d+ from cache \d+\. Device /dev/cas\d+-\d+ is mounted\!"
]

remove_mounted_core_kernel = [
r"Error while removing core device \d+ from cache instance \d+",
r"Device opens or mount are pending to this cache"
]

stop_cache_mounted_core = [
r"Error while removing cache \d+",
r"Can\'t stop cache instance \d+\. Device /dev/cas\d+-\d+ is mounted\!"
]

stop_cache_mounted_core_kernel = [
r"Error while stopping cache \d+",
r"Device opens or mount are pending to this cache"
]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#
# Copyright(c) 2019-2022 Intel Corporation
# Copyright(c) 2024 Huawei Technologies
# SPDX-License-Identifier: BSD-3-Clause
#

Expand All @@ -10,13 +11,13 @@
from storage_devices.disk import DiskType, DiskTypeSet, DiskTypeLowerThan
from test_tools import fs_utils
from test_tools.disk_utils import Filesystem
from test_utils.filesystem.symlink import Symlink
from test_utils.size import Size, Unit

mount_point = "/mnt/cas"
test_file_path = f"{mount_point}/test_file"



@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_load_cache_with_mounted_core():
Expand Down Expand Up @@ -89,6 +90,7 @@ def test_stop_cache_with_mounted_partition():
- No system crash.
- Unable to stop cache when partition is mounted.
- Unable to remove core when partition is mounted.
- casadm displays proper message.
"""
with TestRun.step("Prepare cache and core devices. Start CAS."):
cache_dev = TestRun.disks['cache']
Expand All @@ -104,6 +106,10 @@ def test_stop_cache_with_mounted_partition():
core = cache.add_core(core_part)
core.mount(mount_point)

with TestRun.step("Ensure /etc/mtab exists."):
if not fs_utils.check_if_symlink_exists("/etc/mtab"):
Symlink.create_symlink("/proc/self/mounts", "/etc/mtab")

with TestRun.step("Try to remove core from cache."):
output = TestRun.executor.run_expect_fail(cli.remove_core_cmd(cache_id=str(cache.cache_id),
core_id=str(core.core_id)))
Expand All @@ -119,3 +125,61 @@ def test_stop_cache_with_mounted_partition():
with TestRun.step("Stop cache."):
casadm.stop_all_caches()


@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_stop_cache_with_mounted_partition_no_mtab():
"""
title: Test for removing core and stopping cache when casadm is unable to check mounts.
description: |
Negative test of the ability of CAS to remove core and stop cache while core
is still mounted and casadm is unable to check mounts.
pass_criteria:
- No system crash.
- Unable to stop cache when partition is mounted.
- Unable to remove core when partition is mounted.
- casadm displays proper message informing that mount check was performed by kernel module
"""
with TestRun.step("Prepare cache and core devices. Start CAS."):
cache_dev = TestRun.disks['cache']
cache_dev.create_partitions([Size(1, Unit.GibiByte)])
cache_part = cache_dev.partitions[0]
core_dev = TestRun.disks['core']
core_dev.create_partitions([Size(4, Unit.GibiByte)])
core_part = core_dev.partitions[0]
cache = casadm.start_cache([cache_part], force=True)

with TestRun.step("Add core device with xfs filesystem and mount it."):
core_part.create_filesystem(Filesystem.xfs)
core = cache.add_core(core_part)
core.mount(mount_point)

with TestRun.step("Move /etc/mtab"):
if fs_utils.check_if_symlink_exists("/etc/mtab"):
mtab = Symlink("/etc/mtab")
else:
mtab = Symlink.create_symlink("/proc/self/mounts", "/etc/mtab")
mtab.move("/tmp")

with TestRun.step("Try to remove core from cache."):
output = TestRun.executor.run_expect_fail(cli.remove_core_cmd(cache_id=str(cache.cache_id),
core_id=str(core.core_id)))
cli_messages.check_stderr_msg(output, cli_messages.remove_mounted_core_kernel)

with TestRun.step("Try to stop CAS."):
output = TestRun.executor.run_expect_fail(cli.stop_cmd(cache_id=str(cache.cache_id)))
cli_messages.check_stderr_msg(output, cli_messages.stop_cache_mounted_core_kernel)

with TestRun.step("Unmount core device."):
core.unmount()

with TestRun.step("Remove core."):
core.remove_core()

with TestRun.step("Re-add core."):
cache.add_core(core_part)

with TestRun.step("Stop cache."):
cache.stop()

mtab.move("/etc")