From aa54d977ea04e28e33e4527cfdb3576e28d3de50 Mon Sep 17 00:00:00 2001 From: Peng Yong Date: Wed, 21 Dec 2016 10:36:47 +0800 Subject: [PATCH 1/2] issue 191: compile error on RHEL 7.3 --- src/flashcache_conf.c | 14 +++++++------- src/flashcache_procfs.c | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/flashcache_conf.c b/src/flashcache_conf.c index 0ca05f7..f1c250d 100644 --- a/src/flashcache_conf.c +++ b/src/flashcache_conf.c @@ -92,7 +92,7 @@ static void flashcache_sync_for_remove(struct cache_c *dmc); extern char *flashcache_sw_version; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3) )) static int flashcache_wait_schedule(void *unused) { @@ -1225,7 +1225,7 @@ flashcache_ctr(struct dm_target *ti, unsigned int argc, char **argv) seq_io_move_to_lruhead(dmc, &dmc->seq_recent_ios[i]); } dmc->seq_io_tail = &dmc->seq_recent_ios[0]; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3) )) (void)wait_on_bit_lock(&flashcache_control->synch_flags, FLASHCACHE_UPDATE_LIST, flashcache_wait_schedule, TASK_UNINTERRUPTIBLE); #else @@ -1235,7 +1235,7 @@ flashcache_ctr(struct dm_target *ti, unsigned int argc, char **argv) dmc->next_cache = cache_list_head; cache_list_head = dmc; clear_bit(FLASHCACHE_UPDATE_LIST, &flashcache_control->synch_flags); -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3) )) smp_mb__after_clear_bit(); #else smp_mb__after_atomic(); @@ -1437,7 +1437,7 @@ flashcache_dtr(struct dm_target *ti) DMINFO("cache queued jobs %d", nr_queued); flashcache_dtr_stats_print(dmc); -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3) )) (void)wait_on_bit_lock(&flashcache_control->synch_flags, FLASHCACHE_UPDATE_LIST, flashcache_wait_schedule, @@ -1456,7 +1456,7 @@ flashcache_dtr(struct dm_target *ti) nodepp = &((*nodepp)->next_cache); } clear_bit(FLASHCACHE_UPDATE_LIST, &flashcache_control->synch_flags); -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3) )) smp_mb__after_clear_bit(); #else smp_mb__after_atomic(); @@ -1758,7 +1758,7 @@ flashcache_notify_reboot(struct notifier_block *this, { struct cache_c *dmc; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3) )) (void)wait_on_bit_lock(&flashcache_control->synch_flags, FLASHCACHE_UPDATE_LIST, flashcache_wait_schedule, @@ -1779,7 +1779,7 @@ flashcache_notify_reboot(struct notifier_block *this, } } clear_bit(FLASHCACHE_UPDATE_LIST, &flashcache_control->synch_flags); -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3) )) smp_mb__after_clear_bit(); #else smp_mb__after_atomic(); diff --git a/src/flashcache_procfs.c b/src/flashcache_procfs.c index e7d4078..9c2ada3 100644 --- a/src/flashcache_procfs.c +++ b/src/flashcache_procfs.c @@ -70,7 +70,7 @@ static char *flashcache_cons_sysctl_devname(struct cache_c *dmc); #define FLASHCACHE_PROC_ROOTDIR_NAME "flashcache" static int -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) flashcache_io_latency_init(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) @@ -103,7 +103,7 @@ flashcache_io_latency_init(ctl_table *table, int write, } static int -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) flashcache_sync_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) @@ -135,7 +135,7 @@ flashcache_sync_sysctl(ctl_table *table, int write, } static int -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) flashcache_zerostats_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) @@ -169,7 +169,7 @@ flashcache_zerostats_sysctl(ctl_table *table, int write, } static int -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) flashcache_fallow_clean_speed_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) @@ -200,7 +200,7 @@ flashcache_fallow_clean_speed_sysctl(ctl_table *table, int write, } static int -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) flashcache_dirty_thresh_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) @@ -234,7 +234,7 @@ flashcache_dirty_thresh_sysctl(ctl_table *table, int write, } static int -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) flashcache_lru_hot_pct_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) @@ -272,7 +272,7 @@ flashcache_lru_hot_pct_sysctl(ctl_table *table, int write, static struct flashcache_writeback_sysctl_table { struct ctl_table_header *sysctl_header; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) struct ctl_table vars[FLASHCACHE_NUM_WRITEBACK_SYSCTLS]; struct ctl_table dev[2]; struct ctl_table dir[2]; @@ -553,7 +553,7 @@ static struct flashcache_writeback_sysctl_table { static struct flashcache_writethrough_sysctl_table { struct ctl_table_header *sysctl_header; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) struct ctl_table vars[FLASHCACHE_NUM_WRITETHROUGH_SYSCTLS]; struct ctl_table dev[2]; struct ctl_table dir[2]; @@ -718,7 +718,7 @@ static struct flashcache_writethrough_sysctl_table { }; int * -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) flashcache_find_sysctl_data(struct cache_c *dmc, struct ctl_table *vars) #else flashcache_find_sysctl_data(struct cache_c *dmc, ctl_table *vars) From 39f2b10e46359b61afbb15ff5199c200eb5f3ab6 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Mon, 1 Feb 2016 11:46:39 +0000 Subject: [PATCH 2/2] Switch from ioctl to dm target messages for PID blacklist/whitelist manipulation In mainline 4.4 the ioctl() callback in the DM target has been removed in favour of a prepare_ioctl() which selects the underlying device, all ioctls are assume to apply to that. In discussions with upstream on resolving this it was suggested that the correct mechanism for this kind of target focussed ioctl is actually DM target messages. This patch converts the blacklist/whitelist manipulation over to these DM target messages. It also adds rather primative support to the flashcache_setioctl helper to switch to DM target messages when the existing ioctls are not supported (ENOTTY). This is handled by calling out to dmsetup which offers a message command to form these requests. I would envisage it would be possible to reduce flashcache_setioctl to a simple shell script in the future once there is no possibility of these tools being used with a kernel supporting the ioctl only. This should fix the hard parts of issue #215. fixes: #215 Signed-off-by: Andy Whitcroft --- src/flashcache_conf.c | 5 +++ src/flashcache_ioctl.c | 77 +++++++++++++++++++++++++++++++++ src/flashcache_ioctl.h | 6 +++ src/utils/flashcache_setioctl.c | 60 ++++++++++++++++++++++++- 4 files changed, 147 insertions(+), 1 deletion(-) diff --git a/src/flashcache_conf.c b/src/flashcache_conf.c index f1c250d..98b4b40 100644 --- a/src/flashcache_conf.c +++ b/src/flashcache_conf.c @@ -1713,7 +1713,12 @@ static struct target_type flashcache_target = { .dtr = flashcache_dtr, .map = flashcache_map, .status = flashcache_status, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0) && ( RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3) )) .ioctl = flashcache_ioctl, +#else + .prepare_ioctl = flashcache_prepare_ioctl, + .message = flashcache_message, +#endif .iterate_devices = flashcache_iterate_devices, }; diff --git a/src/flashcache_ioctl.c b/src/flashcache_ioctl.c index 52ac56f..ba1ec82 100644 --- a/src/flashcache_ioctl.c +++ b/src/flashcache_ioctl.c @@ -503,6 +503,81 @@ skip_sequential_io(struct cache_c *dmc, struct bio *bio) * exit, for cases where the process dies after marking itself * non-cacheable. */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) +int +flashcache_prepare_ioctl(struct dm_target *ti, + struct block_device **bdev, fmode_t *mode) +{ + struct cache_c *dmc = (struct cache_c *) ti->private; + + *bdev = dmc->disk_dev->bdev; + + return 0; +} + +int +flashcache_message(struct dm_target *ti, unsigned argc, char **argv) +{ + struct cache_c *dmc = (struct cache_c *) ti->private; + int list; + long long upid; + pid_t pid = 0; + + /* + * whitelist|blacklist add|del + * whitelist|blacklist delall + */ + if (argc < 2) + return -EINVAL; + + /* Decode the primary command. */ + if (strcmp(argv[0], "whitelist") == 0) { + list = FLASHCACHE_WHITELIST; + } else if (strcmp(argv[0], "blacklist") == 0) { + list = FLASHCACHE_BLACKLIST; + } else { + return -EINVAL; + } + + /* Decode the sub-command. */ + if (strcmp(argv[1], "add") == 0) { + if (argc != 3) + return -EINVAL; + + /* Decode the pid. */ + if (kstrtoull(argv[2], 10, &upid)) + return -EINVAL; + pid = (pid_t)upid; + + flashcache_add_pid(dmc, pid, list); + return 0; + + } else if (strcmp(argv[1], "del") == 0) { + if (argc != 3) + return -EINVAL; + + /* Decode the pid. */ + if (kstrtoull(argv[2], 10, &upid)) + return -EINVAL; + pid = (pid_t)upid; + + flashcache_del_pid(dmc, pid, list); + return 0; + + } else if (strcmp(argv[1], "delall") == 0) { + if (argc != 2) + return -EINVAL; + + flashcache_del_all_pids(dmc, list, 0); + return 0; + + } else { + return -EINVAL; + } +} + +#else + int #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27) flashcache_ioctl(struct dm_target *ti, struct inode *inode, @@ -561,3 +636,5 @@ flashcache_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) } } + +#endif diff --git a/src/flashcache_ioctl.h b/src/flashcache_ioctl.h index 105df6f..76b1864 100644 --- a/src/flashcache_ioctl.h +++ b/src/flashcache_ioctl.h @@ -51,6 +51,11 @@ enum { #define FLASHCACHEDELALLWHITELIST _IOW(FLASHCACHE_IOCTL, FLASHCACHEDELWHITELISTALL_CMD, pid_t) #ifdef __KERNEL__ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) || ( RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) )) +int flashcache_message(struct dm_target *ti, unsigned argc, char **argv); +int flashcache_prepare_ioctl(struct dm_target *ti, + struct block_device **bdev, fmode_t *mode); +#else #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27) int flashcache_ioctl(struct dm_target *ti, struct inode *inode, struct file *filp, unsigned int cmd, @@ -59,6 +64,7 @@ int flashcache_ioctl(struct dm_target *ti, struct inode *inode, int flashcache_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg); #endif +#endif void flashcache_pid_expiry_all_locked(struct cache_c *dmc); int flashcache_uncacheable(struct cache_c *dmc, struct bio *bio); void seq_io_remove_from_lru(struct cache_c *dmc, struct sequential_io *seqio); diff --git a/src/utils/flashcache_setioctl.c b/src/utils/flashcache_setioctl.c index 44d5568..d2d7532 100644 --- a/src/utils/flashcache_setioctl.c +++ b/src/utils/flashcache_setioctl.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,55 @@ void usage(char *pname) exit(1); } +void dm_message(char *cachedev, char list, char action, pid_t pid) +{ + char pidstr[32]; + + char *argv[] = { + "/sbin/dmsetup", + "message", + cachedev, + "0", + /* command */ NULL, + /* sub-command */ NULL, + /* pid */ NULL, + NULL, + }; + + switch (list) { + case 'w': + argv[4] = "whitelist"; + break; + case 'b': + argv[4] = "blacklist"; + break; + default: + return; + } + + switch (action) { + case 'a': + argv[5] = "add"; + break; + case 'r': + argv[5] = "del"; + break; + case 'c': + argv[5] = "delall"; + break; + } + + switch (action) { + case 'a': + case 'r': + snprintf(pidstr, sizeof(pidstr), "%lld", (long long)pid); + argv[6] = pidstr; + break; + } + + execv(argv[0], argv); +} + int main(int argc, char **argv) { @@ -50,6 +100,7 @@ main(int argc, char **argv) intmax_t pidmax; char *tmp; pid_t pid; + int err; while ((c = getopt(argc, argv, "carb:w:")) != -1) { switch (c) { @@ -125,11 +176,18 @@ main(int argc, char **argv) break; } } + err = errno; close(cache_fd); + /* + * Failed with an error indicating the ioctl was not appropriate for the device + * switch to using DM messages. + */ + if (result < 0 && err == ENOTTY) { + dm_message(cachedev, list, action, pid); + } if (result < 0) { fprintf(stderr, "ioctl failed on %s\n", cachedev); exit(1); } return 0; } -