From 55cb49507d779bbd53a40d27f48f59732a9028d5 Mon Sep 17 00:00:00 2001 From: Guozhonghua Date: Thu, 7 Aug 2025 09:44:48 +0800 Subject: [PATCH 1/6] Fix two NULL exception. while cow manager inited or reloaded failed, the resource release should be in ordered to avoid NULL pointer access. Signed-off-by: Guozhonghua --- src/cow_manager.c | 49 +++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/cow_manager.c b/src/cow_manager.c index b5f79648..25ff885e 100644 --- a/src/cow_manager.c +++ b/src/cow_manager.c @@ -659,20 +659,21 @@ int cow_reload(const char *path, uint64_t elements, unsigned long sect_size, error: LOG_ERROR(ret, "error during cow manager initialization"); - if (cm->dfilp){ - __close_and_destroy_dattobd_mutable_file(cm->dfilp); - cm->dfilp = NULL; - } - if (cm->sects) { - if (cm->flags & (1 << COW_VMALLOC_UPPER)) - vfree(cm->sects); - else - kfree(cm->sects); - } + if (cm) { + if (cm->dfilp){ + __close_and_destroy_dattobd_mutable_file(cm->dfilp); + cm->dfilp = NULL; + } - if (cm) + if (cm->sects) { + if (cm->flags & (1 << COW_VMALLOC_UPPER)) + vfree(cm->sects); + else + kfree(cm->sects); + } kfree(cm); + } *cm_out = NULL; return ret; @@ -775,21 +776,23 @@ int cow_init(struct snap_device *dev, const char *path, uint64_t elements, unsig error: LOG_ERROR(ret, "error during cow manager initialization"); - if (cm->dfilp){ - file_unlink(cm->dfilp); - __close_and_destroy_dattobd_mutable_file(cm->dfilp); - cm->dfilp = NULL; - } - if (cm->sects) { - if (cm->flags & (1 << COW_VMALLOC_UPPER)) - vfree(cm->sects); - else - kfree(cm->sects); - } + if (cm) { + if (cm->dfilp){ + file_unlink(cm->dfilp); + __close_and_destroy_dattobd_mutable_file(cm->dfilp); + cm->dfilp = NULL; + } + + if (cm->sects) { + if (cm->flags & (1 << COW_VMALLOC_UPPER)) + vfree(cm->sects); + else + kfree(cm->sects); + } - if (cm) kfree(cm); + } *cm_out = NULL; return ret; From a49896606fa30955ea0b902930d1f3b47644dc89 Mon Sep 17 00:00:00 2001 From: Guozhonghua Date: Thu, 7 Aug 2025 09:11:57 +0800 Subject: [PATCH 2/6] Set dev variable after raload. The dev pointer should be set while reloading cow file, otherwise it can cause NULL pointer acess exceptoin while umount after cow file reloaded. Signed-off-by: Guozhonghua --- src/cow_manager.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cow_manager.c b/src/cow_manager.c index 25ff885e..35fe4fa0 100644 --- a/src/cow_manager.c +++ b/src/cow_manager.c @@ -605,6 +605,7 @@ int cow_reload(const char *path, uint64_t elements, unsigned long sect_size, int ret; unsigned long i; struct cow_manager *cm; + struct snap_device *dev; LOG_DEBUG("allocating cow manager"); cm = kzalloc(sizeof(struct cow_manager), GFP_KERNEL); @@ -654,6 +655,11 @@ int cow_reload(const char *path, uint64_t elements, unsigned long sect_size, cm->sects[i].has_data = 1; } + /* Get the dev of the cow manager and set the dev of the cow manager*/ + dev = container_of(cm_out, struct snap_device, sd_cow); + LOG_DEBUG("cow_reload, setting dev of cow manager, cm: %p, dev: %p", cm, dev); + cm->dev = dev; + *cm_out = cm; return 0; From 2378c415abdf467948204648427dc5233a44ad8e Mon Sep 17 00:00:00 2001 From: Guozhonghua Date: Thu, 7 Aug 2025 09:18:05 +0800 Subject: [PATCH 3/6] datto-info file open fail and to release lock. While datto-info file opened failed, the lock grasped should be release, which can cause blocked. Signed-off-by: Guozhonghua --- src/proc_seq_file.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/proc_seq_file.c b/src/proc_seq_file.c index cc9a2484..7faeb7a9 100644 --- a/src/proc_seq_file.c +++ b/src/proc_seq_file.c @@ -245,8 +245,13 @@ static int dattobd_proc_show(struct seq_file *m, void *v) static int dattobd_proc_open(struct inode *inode, struct file *filp) { - mutex_lock(&ioctl_mutex); - return seq_open(filp, &dattobd_seq_proc_ops); + int ret; + mutex_lock(&ioctl_mutex); + ret = seq_open(filp, &dattobd_seq_proc_ops); + if (ret) { + mutex_unlock(&ioctl_mutex); + } + return ret; } static int dattobd_proc_release(struct inode *inode, struct file *file) From 0c7d7bc89ac7e615186179762fd1c1942d778473 Mon Sep 17 00:00:00 2001 From: Guozhonghua Date: Thu, 7 Aug 2025 09:49:45 +0800 Subject: [PATCH 4/6] fiemap api check opt. If the filesystem does not supports fiemap api, such as vfat, it should ignored to replace return error, for the file extent is not used. Signed-off-by: Guozhonghua --- src/cow_manager.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cow_manager.c b/src/cow_manager.c index 35fe4fa0..ac0d1bb9 100644 --- a/src/cow_manager.c +++ b/src/cow_manager.c @@ -505,8 +505,16 @@ int cow_sync_and_close(struct cow_manager *cm) if (ret) goto error; - ret = cow_get_file_extents(cm->dev, cm->dfilp->filp); - if(ret) goto error; + /* + * If the fs support fiemap, we need to get the extents of the file, + * otherwise it is ignored. + */ + if (cm->dfilp->filp->f_inode->i_op && cm->dfilp->filp->f_inode->i_op->fiemap) { + ret = cow_get_file_extents(cm->dev, cm->dfilp->filp); + if(ret) goto error; + } else { + LOG_WARN("fiemap not supported, ignoring extents processing."); + } if (cm->dfilp){ __close_and_destroy_dattobd_mutable_file(cm->dfilp); From 45924159ca5f22e88b58e39ff2e169f83fffa9e8 Mon Sep 17 00:00:00 2001 From: Guozhonghua Date: Sun, 28 Sep 2025 17:55:53 +0800 Subject: [PATCH 5/6] Release the lock after expand cow, otherwise one deadlock occured. Signed-off-by: Guozhonghua --- src/ioctl_handlers.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ioctl_handlers.c b/src/ioctl_handlers.c index 7763f2f1..7597ad8f 100644 --- a/src/ioctl_handlers.c +++ b/src/ioctl_handlers.c @@ -453,6 +453,7 @@ static int ioctl_expand_cow_file(uint64_t size, unsigned int minor) if(ret) goto error; + put_snap_device_array(snap_devices); return 0; error: From 416b95293c47576eb8c137e5c05646722ad34086 Mon Sep 17 00:00:00 2001 From: Guozhonghua Date: Fri, 31 Oct 2025 18:06:50 +0800 Subject: [PATCH 6/6] Using bio_set_dev first for bfq scheduler to avoid NULL pointer access. Signed-off-by: Guozhonghua --- src/bio_helper.c | 7 +++---- .../feature-tests/bio_set_dev.c | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 src/configure-tests/feature-tests/bio_set_dev.c diff --git a/src/bio_helper.c b/src/bio_helper.c index 56ac483a..995d3271 100644 --- a/src/bio_helper.c +++ b/src/bio_helper.c @@ -44,11 +44,10 @@ struct request_queue *dattobd_bio_get_queue(struct bio *bio) */ void dattobd_bio_set_dev(struct bio *bio, struct block_device *bdev) { -#ifdef HAVE_BIO_BI_BDEV - //#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - bio->bi_bdev = bdev; -#else +#ifdef HAVE_BIO_SET_DEV bio_set_dev(bio, bdev); +#else + bio->bi_bdev = bdev; #endif } diff --git a/src/configure-tests/feature-tests/bio_set_dev.c b/src/configure-tests/feature-tests/bio_set_dev.c new file mode 100644 index 00000000..b9e15b94 --- /dev/null +++ b/src/configure-tests/feature-tests/bio_set_dev.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Feature test: detect presence of bio_set_dev(bio, bdev) + */ + +#include "includes.h" + +MODULE_LICENSE("GPL"); + +static inline void dummy(void) +{ + struct bio *b = NULL; + struct block_device *d = NULL; + /* compile-time presence check */ + bio_set_dev(b, d); +} + +