diff options
author | Johannes Berg <johannes.berg@intel.com> | 2017-02-07 21:00:14 +0100 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2017-02-07 21:30:54 +0100 |
commit | 11370084bb535afd5935132fc1cb51ae8278cb43 (patch) | |
tree | 9a5f962ec460e465d5c289be4f7da12f320507ae /backport | |
parent | e756ec177e8485b94c4ec211bfd249680e7b4e36 (diff) |
backports: add dev_coredumpsg() where needed
Add dev_coredumpsg() on kernels where dev_coredumpm() is present
but _sg() isn't, and restrict building appropriately.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'backport')
-rw-r--r-- | backport/backport-include/linux/bp-devcoredump.h | 5 | ||||
-rw-r--r-- | backport/compat/Kconfig | 1 | ||||
-rw-r--r-- | backport/compat/backport-4.7.c | 61 |
3 files changed, 67 insertions, 0 deletions
diff --git a/backport/backport-include/linux/bp-devcoredump.h b/backport/backport-include/linux/bp-devcoredump.h index f116bd2e..56b22751 100644 --- a/backport/backport-include/linux/bp-devcoredump.h +++ b/backport/backport-include/linux/bp-devcoredump.h @@ -1,6 +1,7 @@ #ifndef __BACKPORT_LINUX_DEVCOREDUMP_H #define __BACKPORT_LINUX_DEVCOREDUMP_H #include <linux/version.h> +#include <linux/scatterlist.h> /* We only need to add our wrapper inside the range from 3.18 until * 4.6, outside that we can let our BPAUTO mechanism handle it. @@ -21,6 +22,10 @@ void backport_dev_coredumpm(struct device *dev, struct module *owner, #define dev_coredumpm LINUX_BACKPORT(dev_coredumpm) +#define dev_coredumpsg LINUX_BACKPORT(dev_coredumpsg) +void dev_coredumpsg(struct device *dev, struct scatterlist *table, + size_t datalen, gfp_t gfp); + #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) && \ LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)) */ diff --git a/backport/compat/Kconfig b/backport/compat/Kconfig index f66d5f74..335d9058 100644 --- a/backport/compat/Kconfig +++ b/backport/compat/Kconfig @@ -128,6 +128,7 @@ config BPAUTO_WANT_DEV_COREDUMP config BPAUTO_BUILD_WANT_DEV_COREDUMP bool + depends on KERNEL_3_18 default n if DEV_COREDUMP default n if DISABLE_DEV_COREDUMP default y if BPAUTO_WANT_DEV_COREDUMP diff --git a/backport/compat/backport-4.7.c b/backport/compat/backport-4.7.c index 14f8da11..25a00235 100644 --- a/backport/compat/backport-4.7.c +++ b/backport/compat/backport-4.7.c @@ -115,3 +115,64 @@ int nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen, return 0; } EXPORT_SYMBOL_GPL(nla_put_64bit); + +/* below 3.18 we copied the entire devcoredump */ +#if LINUX_VERSION_IS_GEQ(3,18,0) +#include <linux/devcoredump.h> +#include <linux/scatterlist.h> + +static void devcd_free_sgtable(void *data) +{ + struct scatterlist *table = data; + int i; + struct page *page; + struct scatterlist *iter; + struct scatterlist *delete_iter; + + /* free pages */ + iter = table; + for_each_sg(table, iter, sg_nents(table), i) { + page = sg_page(iter); + if (page) + __free_page(page); + } + + /* then free all chained tables */ + iter = table; + delete_iter = table; /* always points on a head of a table */ + while (!sg_is_last(iter)) { + iter++; + if (sg_is_chain(iter)) { + iter = sg_chain_ptr(iter); + kfree(delete_iter); + delete_iter = iter; + } + } + + /* free the last table */ + kfree(delete_iter); +} + +static ssize_t devcd_read_from_sgtable(char *buffer, loff_t offset, + size_t buf_len, void *data, + size_t data_len) +{ + struct scatterlist *table = data; + + if (offset > data_len) + return -EINVAL; + + if (offset + buf_len > data_len) + buf_len = data_len - offset; + return sg_pcopy_to_buffer(table, sg_nents(table), buffer, buf_len, + offset); +} + +void dev_coredumpsg(struct device *dev, struct scatterlist *table, + size_t datalen, gfp_t gfp) +{ + dev_coredumpm(dev, THIS_MODULE, table, datalen, gfp, + devcd_read_from_sgtable, devcd_free_sgtable); +} +EXPORT_SYMBOL_GPL(dev_coredumpsg); +#endif /* >= 3.18.0 */ |