Skip to content

Commit

Permalink
DattoBD 0.11.10 Release (#400)
Browse files Browse the repository at this point in the history
* Rewrote priorities of blk_alloc_queue variants (#5)

`blk_alloc_queue` had problems with correct priorities of definitions being used, which led to usage of `blk_alloc_queue(NUMA_NO_NODE)` instead of `blk_alloc_queue(GFP_KERNEL)` in some specific cases.

* Kernel 6.X support (#7)

* Implemented struct bdev_handle to replace it on older kernels; Modified fields of snap_device and surrounding functions to use bdev_handle instead of block_device.

* Modified bdev_freeze/thaw references according to Kernel 6.8

* Added emulation of debian/control file for Ubuntu 24.04 LTS

* Discovered that dpkg-gensymbols looks for debian/control only in current directory

* Fixed includes to handle bdev_handle correctly

* Kernel 6.6+ uses super_block as block_device holder

* Tracer destroy now destroys bdev_handle correctly

* Added vm_area_struct_vm_lock feature test

* Made functions inside cow_get_file_extents to return correct error codes, not shadowed ones

* Added test for vma_lock cache area

* Added vm_lock initialization during page stealing at cow_get_file_extents

* Fixed symbol test newline

* Renamed dattobd_blkdev_by_path so we will have correct prefix

dattobd_blkdev_by_path was previously named dattodb_blkdev_by_path, which is incorrect, as our module is called dattobd.

* Fixed symbol-tests again

It used CRLF instead of LF which led to incorrect behavior

* Patch to support Rocky 9.5

* Fix usage of old filp

* Version bump

* Patch to have a workaround with DKMS bug

Dell introduced a logic-breaking change in dell/dkms#461 which led to incorrect DattoBD installation behavior on RHEL systems. This patch has a small workaround to deal with that.

* Improved stability of DKMS workaround

Improved stability of DKMS workaround as it was proposed in dell/dkms#461
  • Loading branch information
iamandrii authored Dec 19, 2024
1 parent b5b16d4 commit 229ca99
Show file tree
Hide file tree
Showing 23 changed files with 334 additions and 114 deletions.
13 changes: 12 additions & 1 deletion dist/dattobd.spec
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@


Name: dattobd
Version: 0.11.9
Version: 0.11.10
Release: 1%{?dist}
Summary: Kernel module and utilities for enabling low-level live backups
Vendor: Datto, Inc.
Expand Down Expand Up @@ -320,6 +320,13 @@ sed -e "s:@prefix@:%{_prefix}:g" \
# Generate symbols for library package (Debian/Ubuntu only)
%if "%{_vendor}" == "debbuild"
mkdir -p %{buildroot}/%{libname}/DEBIAN

# Ubuntu 24.04 LTS have broken dpkg-gensymbols usage without debian/control file. So, let us emulate it.
%if 0%{?ubuntu} && 0%{?ubuntu} >= 2404
mkdir debian
touch debian/control
%endif

dpkg-gensymbols -P%{buildroot} -p%{libname} -v%{version}-%{release} -e%{buildroot}%{_libdir}/%{libprefix}.so.%{?!libsover:0}%{?libsover} -e%{buildroot}%{_libdir}/%{libprefix}.so.%{?!libsover:0}%{?libsover}.* -O%{buildroot}/%{libname}/DEBIAN/symbols
%endif

Expand Down Expand Up @@ -425,6 +432,10 @@ if [ "$1" -ge "1" ]; then
if [ -f /usr/lib/dkms/common.postinst ]; then
/usr/lib/dkms/common.postinst %{name} %{version}
exit $?
else
dkms add -m %{name} -v %{version} %{?rpm_dkms_opt:--rpm_safe_upgrade}
dkms install -m %{name} -v %{version} --force
exit $?
fi
fi

Expand Down
20 changes: 10 additions & 10 deletions src/bdev_state_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ int __handle_bdev_mount_nowrite(const struct vfsmount *mnt,
{
if (!dev || !test_bit(ACTIVE, &dev->sd_state) ||
tracer_read_fail_state(dev) ||
dev->sd_base_dev != mnt->mnt_sb->s_bdev)
dev->sd_base_dev->bdev != mnt->mnt_sb->s_bdev)
continue;

if (mnt == dev->sd_cow->dfilp->mnt) {
Expand Down Expand Up @@ -105,7 +105,7 @@ int __handle_bdev_mount_writable(const char *dir_name,
int ret;
unsigned int i;
struct snap_device *dev;
struct block_device *cur_bdev;
struct bdev_wrapper *cur_bdev;

LOG_DEBUG("ENTER %s", __func__);
tracer_for_each(dev, i)
Expand All @@ -121,7 +121,7 @@ int __handle_bdev_mount_writable(const char *dir_name,
if (test_bit(UNVERIFIED, &dev->sd_state)) {
// get the block device for the unverified tracer we are
// looking into
cur_bdev = dattodb_blkdev_by_path(dev->sd_bdev_path,
cur_bdev = dattobd_blkdev_by_path(dev->sd_bdev_path,
FMODE_READ, NULL);
if (IS_ERR(cur_bdev)) {
cur_bdev = NULL;
Expand All @@ -130,7 +130,7 @@ int __handle_bdev_mount_writable(const char *dir_name,

// if the tracer's block device exists and matches the
// one being mounted perform transition
if (cur_bdev == bdev) {
if (cur_bdev->bdev == bdev) {
LOG_DEBUG("block device mount detected for "
"unverified device %d",
i);
Expand All @@ -144,7 +144,7 @@ int __handle_bdev_mount_writable(const char *dir_name,
// put the block device
dattobd_blkdev_put(cur_bdev);

} else if (dev->sd_base_dev == bdev) {
} else if (dev->sd_base_dev->bdev == bdev) {
LOG_DEBUG(
"block device mount detected for dormant device %d",
i);
Expand Down Expand Up @@ -259,15 +259,15 @@ void post_umount_check(int dormant_ret, int umount_ret, unsigned int idx,
// if we successfully went dormant, but the umount call failed,
// reactivate
if (umount_ret) {
struct block_device *bdev;
bdev = dattodb_blkdev_by_path(dev->sd_bdev_path, FMODE_READ, NULL);
if (!bdev || IS_ERR(bdev)) {
struct bdev_wrapper *bdev_w;
bdev_w = dattobd_blkdev_by_path(dev->sd_bdev_path, FMODE_READ, NULL);
if (IS_ERR_OR_NULL(bdev_w)) {
LOG_DEBUG("device gone, moving to error state");
tracer_set_fail_state(dev, -ENODEV);
return;
}

dattobd_blkdev_put(bdev);
dattobd_blkdev_put(bdev_w);

LOG_DEBUG("umount call failed, reactivating tracer %u", idx);
auto_transition_active(idx, dir_name);
Expand All @@ -279,7 +279,7 @@ void post_umount_check(int dormant_ret, int umount_ret, unsigned int idx,

// if we went dormant, but the block device is still mounted somewhere,
// goto fail state
sb = dattobd_get_super(dev->sd_base_dev);
sb = dattobd_get_super(dev->sd_base_dev->bdev);
if (sb) {
if (!(sb->s_flags & MS_RDONLY)) {
LOG_ERROR(
Expand Down
77 changes: 52 additions & 25 deletions src/blkdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

#include "blkdev.h"
#include "logging.h"
#include <linux/version.h>

#if !defined HAVE_BLKDEV_GET_BY_PATH && !defined HAVE_BLKDEV_GET_BY_PATH_4
#if !defined HAVE_BLKDEV_GET_BY_PATH && !defined HAVE_BLKDEV_GET_BY_PATH_4 && !defined HAVE_BDEV_OPEN_BY_PATH && !defined HAVE_BDEV_FILE_OPEN_BY_PATH

/**
* dattobd_lookup_bdev() - Looks up the inode associated with the path, verifies
Expand Down Expand Up @@ -91,30 +92,44 @@ static struct block_device *_blkdev_get_by_path(const char *pathname, fmode_t mo
#endif

/**
* dattodb_blkdev_by_path() - Fetches the @block_device struct associated with the
* dattobd_blkdev_by_path() - Fetches the @block_device struct associated with the
* @path. This function uses different methods based on available kernel functions
* to retrieve the block device.
* to retrieve the block device. Returns @bdev_handle struct which contains
* information about @block_device and @holder. Made to be in compliance with kernel
* version 6.8+ standard.
*
* @path: the path name of a block special file.
* @mode: The mode used to open the block special file, likely just FMODE_READ.
* @holder: unused.
*
* Return:
* On success the @block_device structure otherwise an error created via
* On success the @bdev_handle structure otherwise an error created via
* ERR_PTR().
*/
struct block_device *dattodb_blkdev_by_path(const char *path, fmode_t mode,
struct bdev_wrapper *dattobd_blkdev_by_path(const char *path, fmode_t mode,
void *holder)
{
#if defined HAVE_BLKDEV_GET_BY_PATH_4
return blkdev_get_by_path(path, mode, holder, NULL);
struct bdev_wrapper *bw = kmalloc(sizeof(struct bdev_wrapper), GFP_KERNEL);

#elif defined HAVE_BLKDEV_GET_BY_PATH
return blkdev_get_by_path(path, mode, holder);
if(IS_ERR_OR_NULL(bw)){
return ERR_PTR(-ENOMEM);
}

#if defined HAVE_BDEV_OPEN_BY_PATH
bw->_internal.handle = bdev_open_by_path(path, mode, holder, NULL);
bw->bdev = bw->_internal.handle->bdev;
#elif defined HAVE_BLKDEV_GET_BY_PATH_4
bw->bdev = blkdev_get_by_path(path, mode, holder, NULL);
#elif defined HAVE_BLKDEV_GET_BY_PATH
bw->bdev = blkdev_get_by_path(path, mode, holder);
#elif defined HAVE_BDEV_FILE_OPEN_BY_PATH
bw->_internal.file = bdev_file_open_by_path(path, mode, holder, NULL);
bw->bdev = file_bdev(bw->_internal.file);
#else
return _blkdev_get_by_path(path, mode, holder);
bw->bdev = _blkdev_get_by_path(path, mode, holder);
#endif

return bw;
}

/**
Expand All @@ -131,13 +146,15 @@ struct super_block *dattobd_get_super(struct block_device * bd)
{
#if defined HAVE_BD_SUPER
return (bd != NULL) ? bd->bd_super : NULL;

#elif defined HAVE_GET_SUPER
return get_super(bdev);

#else
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6,6,0)
return (struct super_block*)(bd -> bd_holder);
#elif GET_ACTIVE_SUPER_ADDR != 0
struct super_block* (*get_active_superblock)(struct block_device*)= (GET_ACTIVE_SUPER_ADDR != 0) ? (struct super_block* (*)(struct block_device*))(GET_ACTIVE_SUPER_ADDR +(long long)(((void*)kfree)-(void*)KFREE_ADDR)):NULL;
return get_active_superblock(bd);
#else
#error "Could not determine super block of block device"
#endif
}

Expand All @@ -155,12 +172,14 @@ void dattobd_drop_super(struct super_block *sb)
{
#if defined HAVE_BD_SUPER
return;

#elif defined HAVE_GET_SUPER
return drop_super(sb);

#else
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6,6,0)
return;
#elif GET_ACTIVE_SUPER_ADDR != 0
return;
#else
#error "Could not determine super block of block device"
#endif
}

Expand All @@ -169,22 +188,30 @@ void dattobd_drop_super(struct super_block *sb)
* This function performs the appropriate action based on the available
* kernel functions to release block device.
*
* @bd: block device structure pointer to be released.
* @bh: bdev_handle structure pointer to be released.
*
* Return:
* void.
*/
void dattobd_blkdev_put(struct block_device *bd)
void dattobd_blkdev_put(struct bdev_wrapper *bw)
{
#if defined HAVE_BLKDEV_PUT_1
return blkdev_put(bd);

if(unlikely(IS_ERR_OR_NULL(bw)))
return;

#ifdef USE_BDEV_AS_FILE
if(bw->_internal.file)
bdev_fput(bw->_internal.file);
#elif defined HAVE_BDEV_RELEASE
if(bw->_internal.handle)
bdev_release(bw->_internal.handle);
#elif defined HAVE_BLKDEV_PUT_1
blkdev_put(bw->bdev);
#elif defined HAVE_BLKDEV_PUT_2
return blkdev_put(bd,NULL);

blkdev_put(bw->bdev, NULL);
#else
return blkdev_put(bd, FMODE_READ);
blkdev_put(bw->bdev, FMODE_READ);
#endif
kfree(bw);
}

/**
Expand Down Expand Up @@ -219,7 +246,7 @@ int dattobd_get_start_sect_by_gendisk_for_bio(struct gendisk* gd, u8 partno, sec
LOG_ERROR(-1, "Unreachable code.");
return -1;
#else
#error Could not determine starting sector of partition by gendisk and partition number
#error "Could not determine starting sector of partition by gendisk and partition number"
#endif
}

Expand Down
20 changes: 18 additions & 2 deletions src/blkdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#ifndef BLKDEV_H_
#define BLKDEV_H_

#include "config.h"
#include "includes.h"

struct block_device;
Expand All @@ -16,6 +17,21 @@ struct block_device;
#define bdev_whole(bdev) ((bdev)->bd_contains)
#endif

struct bdev_wrapper{
struct block_device* bdev;

union {
#ifdef HAVE_BDEV_HANDLE
struct bdev_handle* handle;
#endif
// Kernel 6.9+ manages block_device with struct file and file_bdev has to be used to find block_device from file.
// For us, file_bdev function is marker to check if we have to use
#ifdef USE_BDEV_AS_FILE
struct file* file;
#endif
} _internal;
};

#ifndef HAVE_HD_STRUCT
//#if LINUX_VERSION_CODE < KERNEL_VERSION(5,11,0)
#define dattobd_bdev_size(bdev) (bdev_nr_sectors(bdev))
Expand All @@ -27,14 +43,14 @@ struct block_device;
#endif


struct block_device *dattodb_blkdev_by_path(const char *path, fmode_t mode,
struct bdev_wrapper *dattobd_blkdev_by_path(const char *path, fmode_t mode,
void *holder);

struct super_block *dattobd_get_super(struct block_device * bd);

void dattobd_drop_super(struct super_block *sb);

void dattobd_blkdev_put(struct block_device *bd);
void dattobd_blkdev_put(struct bdev_wrapper *bd);

int dattobd_get_start_sect_by_gendisk_for_bio(struct gendisk* gd, u8 partno, sector_t* result);

Expand Down
5 changes: 5 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#if defined HAVE_BDEV_FILE_OPEN_BY_PATH && defined HAVE_FILE_BDEV

#define USE_BDEV_AS_FILE

#endif
19 changes: 19 additions & 0 deletions src/configure-tests/feature-tests/bdev_file_open_by_path.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-only

/*
* Copyright (C) 2024 Datto Inc.
*/

#include "includes.h"

MODULE_LICENSE("GPL");

static inline void dummy(void){
struct file *file __attribute__ ((unused)) = NULL;
const char *path = "";
fmode_t mode = 0;
void *holder = NULL;
struct blk_holder_ops h;

file = bdev_file_open_by_path(path, mode, holder, &h);
}
15 changes: 15 additions & 0 deletions src/configure-tests/feature-tests/bdev_freeze.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-only

/*
* Copyright (C) 2024 Datto Inc.
*/

#include "includes.h"

MODULE_LICENSE("GPL");

static inline void dummy(void){
struct block_device bh;

bdev_freeze(&bh);
}
19 changes: 19 additions & 0 deletions src/configure-tests/feature-tests/bdev_handle.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-only

/*
* Copyright (C) 2024 Datto Inc.
*/

#include "includes.h"

MODULE_LICENSE("GPL");

static inline void dummy(void){
struct bdev_handle bh;

struct block_device bd;
int holder;

bh.bdev = &bd;
bh.holder = (void*)&holder;
}
20 changes: 20 additions & 0 deletions src/configure-tests/feature-tests/bdev_open_by_path.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0-only

/*
* Copyright (C) 2024 Datto Inc.
*/

#include "includes.h"

MODULE_LICENSE("GPL");

static inline void dummy(void){
struct bdev_handle* bh;

const char *path;
blk_mode_t mode;
int holder;
const struct blk_holder_ops bho;

bh = bdev_open_by_path(path, mode, (void*)&holder, &bho);
}
Loading

0 comments on commit 229ca99

Please sign in to comment.