1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2019 SUSE LLC 4f08c3bdfSopenharmony_ci * Author: Christian Amann <camann@suse.com> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * Tests the ioctl functionality to deduplicate fileranges using 7f08c3bdfSopenharmony_ci * btrfs filesystem. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * 1) Sets the same contents for two files and deduplicates it. 10f08c3bdfSopenharmony_ci * Deduplicates 3 bytes and set the status to 11f08c3bdfSopenharmony_ci * FILE_DEDUPE_RANGE_SAME. 12f08c3bdfSopenharmony_ci * 2) Sets different content for two files and tries to 13f08c3bdfSopenharmony_ci * deduplicate it. 0 bytes get deduplicated and status is 14f08c3bdfSopenharmony_ci * set to FILE_DEDUPE_RANGE_DIFFERS. 15f08c3bdfSopenharmony_ci * 3) Sets same content for two files but sets the length to 16f08c3bdfSopenharmony_ci * deduplicate to -1. ioctl(FIDEDUPERANGE) fails with EINVAL. 17f08c3bdfSopenharmony_ci */ 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci#include "config.h" 20f08c3bdfSopenharmony_ci#include <stdlib.h> 21f08c3bdfSopenharmony_ci#include <sys/ioctl.h> 22f08c3bdfSopenharmony_ci#include <errno.h> 23f08c3bdfSopenharmony_ci#include "tst_test.h" 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#ifdef HAVE_STRUCT_FILE_DEDUPE_RANGE 26f08c3bdfSopenharmony_ci#include <linux/fs.h> 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_ci#define SUCCESS 0 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#define MNTPOINT "mnt_point" 31f08c3bdfSopenharmony_ci#define FILE_SRC_PATH MNTPOINT"/file_src" 32f08c3bdfSopenharmony_ci#define FILE_DEST_PATH MNTPOINT"/file_dest" 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_cistatic int fd_src; 35f08c3bdfSopenharmony_cistatic int fd_dest; 36f08c3bdfSopenharmony_cistatic struct file_dedupe_range *fdr; 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_cistatic struct tcase { 39f08c3bdfSopenharmony_ci uint64_t src_length; 40f08c3bdfSopenharmony_ci char *src_fcontents; 41f08c3bdfSopenharmony_ci char *dest_fcontents; 42f08c3bdfSopenharmony_ci int exp_err; 43f08c3bdfSopenharmony_ci uint64_t bytes_deduped; 44f08c3bdfSopenharmony_ci int status; 45f08c3bdfSopenharmony_ci} tcases[] = { 46f08c3bdfSopenharmony_ci {3, "AAA", "AAA", SUCCESS, 3, FILE_DEDUPE_RANGE_SAME}, 47f08c3bdfSopenharmony_ci {3, "AAA", "AAB", SUCCESS, 0, FILE_DEDUPE_RANGE_DIFFERS}, 48f08c3bdfSopenharmony_ci {-1, "AAA", "AAA", EINVAL, 0, 0}, 49f08c3bdfSopenharmony_ci}; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_cistatic void verify_ioctl(unsigned int n) 52f08c3bdfSopenharmony_ci{ 53f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci fd_src = SAFE_OPEN(FILE_SRC_PATH, O_RDWR | O_CREAT, 0664); 56f08c3bdfSopenharmony_ci fd_dest = SAFE_OPEN(FILE_DEST_PATH, O_RDWR | O_CREAT, 0664); 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd_src, tc->src_fcontents, strlen(tc->src_fcontents)); 59f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd_dest, tc->dest_fcontents, strlen(tc->dest_fcontents)); 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci memset(fdr, 0, sizeof(struct file_dedupe_range) + 62f08c3bdfSopenharmony_ci sizeof(struct file_dedupe_range_info)); 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci fdr->src_length = tc->src_length; 65f08c3bdfSopenharmony_ci fdr->dest_count = 1; 66f08c3bdfSopenharmony_ci fdr->info[0].dest_fd = fd_dest; 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci TEST(ioctl(fd_src, FIDEDUPERANGE, fdr)); 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ci if (tc->exp_err != TST_ERR) { 71f08c3bdfSopenharmony_ci tst_res(TFAIL, 72f08c3bdfSopenharmony_ci "ioctl(FIDEDUPERANGE) ended with %s, expected %s", 73f08c3bdfSopenharmony_ci tst_strerrno(TST_ERR), tst_strerrno(tc->exp_err)); 74f08c3bdfSopenharmony_ci return; 75f08c3bdfSopenharmony_ci } 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci if (fdr->info[0].bytes_deduped != tc->bytes_deduped) { 78f08c3bdfSopenharmony_ci tst_res(TFAIL, 79f08c3bdfSopenharmony_ci "ioctl(FIDEDUPERANGE) deduplicated %lld bytes, expected %ld. Status: %d", 80f08c3bdfSopenharmony_ci fdr->info[0].bytes_deduped, tc->bytes_deduped, 81f08c3bdfSopenharmony_ci fdr->info[0].status); 82f08c3bdfSopenharmony_ci return; 83f08c3bdfSopenharmony_ci } 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci if (fdr->info[0].status != tc->status) { 86f08c3bdfSopenharmony_ci tst_res(TFAIL, 87f08c3bdfSopenharmony_ci "ioctl(FIDEDUPERANGE) status set to %d, expected %d", 88f08c3bdfSopenharmony_ci fdr->info[0].status, tc->status); 89f08c3bdfSopenharmony_ci return; 90f08c3bdfSopenharmony_ci } 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci tst_res(TPASS, "ioctl(FIDEDUPERANGE) ended with %s as expected", 93f08c3bdfSopenharmony_ci tst_strerrno(tc->exp_err)); 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci SAFE_CLOSE(fd_dest); 96f08c3bdfSopenharmony_ci SAFE_CLOSE(fd_src); 97f08c3bdfSopenharmony_ci} 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_cistatic void cleanup(void) 100f08c3bdfSopenharmony_ci{ 101f08c3bdfSopenharmony_ci if (fd_dest > 0) 102f08c3bdfSopenharmony_ci SAFE_CLOSE(fd_dest); 103f08c3bdfSopenharmony_ci if (fd_src > 0) 104f08c3bdfSopenharmony_ci SAFE_CLOSE(fd_src); 105f08c3bdfSopenharmony_ci if (fdr) 106f08c3bdfSopenharmony_ci free(fdr); 107f08c3bdfSopenharmony_ci} 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_cistatic void setup(void) 110f08c3bdfSopenharmony_ci{ 111f08c3bdfSopenharmony_ci fdr = SAFE_MALLOC(sizeof(struct file_dedupe_range) + 112f08c3bdfSopenharmony_ci sizeof(struct file_dedupe_range_info)); 113f08c3bdfSopenharmony_ci} 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_cistatic struct tst_test test = { 117f08c3bdfSopenharmony_ci .test = verify_ioctl, 118f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 119f08c3bdfSopenharmony_ci .setup = setup, 120f08c3bdfSopenharmony_ci .cleanup = cleanup, 121f08c3bdfSopenharmony_ci .min_kver = "4.5", 122f08c3bdfSopenharmony_ci .needs_root = 1, 123f08c3bdfSopenharmony_ci .mount_device = 1, 124f08c3bdfSopenharmony_ci .mntpoint = MNTPOINT, 125f08c3bdfSopenharmony_ci .dev_fs_type = "btrfs", 126f08c3bdfSopenharmony_ci .needs_drivers = (const char *const[]) { 127f08c3bdfSopenharmony_ci "btrfs", 128f08c3bdfSopenharmony_ci NULL, 129f08c3bdfSopenharmony_ci }, 130f08c3bdfSopenharmony_ci}; 131f08c3bdfSopenharmony_ci#else 132f08c3bdfSopenharmony_ci TST_TEST_TCONF( 133f08c3bdfSopenharmony_ci "This system does not provide support for ioctl(FIDEDUPERANGE)"); 134f08c3bdfSopenharmony_ci#endif 135