Skip to content

Commit

Permalink
selftests/filesystems: add a vfat RENAME_EXCHANGE test
Browse files Browse the repository at this point in the history
Add a test for the renameat2 RENAME_EXCHANGE support in vfat, but split it
in a tool that just does the rename exchange and a script that is run by
the kselftests framework on `make TARGETS="filesystems/fat" kselftest`.

That way the script can be easily extended to test other file operations.

The script creates a 1 MiB disk image, that is then formated with a vfat
filesystem and mounted using a loop device.  That way all file operations
are done on an ephemeral filesystem.

Link: https://lkml.kernel.org/r/20220610075721.1182745-5-javierm@redhat.com
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Muhammad Usama Anjum <usama.anjum@collabora.com>
Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Alexander Larsson <alexl@redhat.com>
Cc: Christian Kellner <ckellner@redhat.com>
Cc: Chung-Chiang Cheng <cccheng@synology.com>
Cc: Colin Walters <walters@verbum.org>
Cc: Lennart Poettering <lennart@poettering.net>
Cc: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
  • Loading branch information
Javier Martinez Canillas authored and akpm committed Jun 17, 2022
1 parent da87e17 commit dd7c9be
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 0 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -20891,6 +20891,7 @@ M: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
S: Maintained
F: Documentation/filesystems/vfat.rst
F: fs/fat/
F: tools/testing/selftests/filesystems/fat/

VFIO DRIVER
M: Alex Williamson <alex.williamson@redhat.com>
Expand Down
1 change: 1 addition & 0 deletions tools/testing/selftests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ TARGETS += exec
TARGETS += filesystems
TARGETS += filesystems/binderfs
TARGETS += filesystems/epoll
TARGETS += filesystems/fat
TARGETS += firmware
TARGETS += fpu
TARGETS += ftrace
Expand Down
2 changes: 2 additions & 0 deletions tools/testing/selftests/filesystems/fat/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
rename_exchange
7 changes: 7 additions & 0 deletions tools/testing/selftests/filesystems/fat/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0

TEST_PROGS := run_fat_tests.sh
TEST_GEN_PROGS_EXTENDED := rename_exchange
CFLAGS += -O2 -g -Wall $(KHDR_INCLUDES)

include ../../lib.mk
2 changes: 2 additions & 0 deletions tools/testing/selftests/filesystems/fat/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CONFIG_BLK_DEV_LOOP=y
CONFIG_VFAT_FS=y
37 changes: 37 additions & 0 deletions tools/testing/selftests/filesystems/fat/rename_exchange.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Program that atomically exchanges two paths using
* the renameat2() system call RENAME_EXCHANGE flag.
*
* Copyright 2022 Red Hat Inc.
* Author: Javier Martinez Canillas <javierm@redhat.com>
*/

#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

void print_usage(const char *program)
{
printf("Usage: %s [oldpath] [newpath]\n", program);
printf("Atomically exchange oldpath and newpath\n");
}

int main(int argc, char *argv[])
{
int ret;

if (argc != 3) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}

ret = renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_EXCHANGE);
if (ret) {
perror("rename exchange failed");
exit(EXIT_FAILURE);
}

exit(EXIT_SUCCESS);
}
82 changes: 82 additions & 0 deletions tools/testing/selftests/filesystems/fat/run_fat_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Run filesystem operations tests on an 1 MiB disk image that is formatted with
# a vfat filesystem and mounted in a temporary directory using a loop device.
#
# Copyright 2022 Red Hat Inc.
# Author: Javier Martinez Canillas <javierm@redhat.com>

set -e
set -u
set -o pipefail

BASE_DIR="$(dirname $0)"
TMP_DIR="$(mktemp -d /tmp/fat_tests_tmp.XXXX)"
IMG_PATH="${TMP_DIR}/fat.img"
MNT_PATH="${TMP_DIR}/mnt"

cleanup()
{
mountpoint -q "${MNT_PATH}" && unmount_image
rm -rf "${TMP_DIR}"
}
trap cleanup SIGINT SIGTERM EXIT

create_loopback()
{
touch "${IMG_PATH}"
chattr +C "${IMG_PATH}" >/dev/null 2>&1 || true

truncate -s 1M "${IMG_PATH}"
mkfs.vfat "${IMG_PATH}" >/dev/null 2>&1
}

mount_image()
{
mkdir -p "${MNT_PATH}"
sudo mount -o loop "${IMG_PATH}" "${MNT_PATH}"
}

rename_exchange_test()
{
local rename_exchange="${BASE_DIR}/rename_exchange"
local old_path="${MNT_PATH}/old_file"
local new_path="${MNT_PATH}/new_file"

echo old | sudo tee "${old_path}" >/dev/null 2>&1
echo new | sudo tee "${new_path}" >/dev/null 2>&1
sudo "${rename_exchange}" "${old_path}" "${new_path}" >/dev/null 2>&1
sudo sync -f "${MNT_PATH}"
grep new "${old_path}" >/dev/null 2>&1
grep old "${new_path}" >/dev/null 2>&1
}

rename_exchange_subdir_test()
{
local rename_exchange="${BASE_DIR}/rename_exchange"
local dir_path="${MNT_PATH}/subdir"
local old_path="${MNT_PATH}/old_file"
local new_path="${dir_path}/new_file"

sudo mkdir -p "${dir_path}"
echo old | sudo tee "${old_path}" >/dev/null 2>&1
echo new | sudo tee "${new_path}" >/dev/null 2>&1
sudo "${rename_exchange}" "${old_path}" "${new_path}" >/dev/null 2>&1
sudo sync -f "${MNT_PATH}"
grep new "${old_path}" >/dev/null 2>&1
grep old "${new_path}" >/dev/null 2>&1
}

unmount_image()
{
sudo umount "${MNT_PATH}" &> /dev/null
}

create_loopback
mount_image
rename_exchange_test
rename_exchange_subdir_test
unmount_image

exit 0

0 comments on commit dd7c9be

Please sign in to comment.