%PDF- %PDF-
| Direktori : /usr/src/blksnap-6.3.0.73/ |
| Current File : //usr/src/blksnap-6.3.0.73/tracker.h |
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __BLK_SNAP_TRACKER_H
#define __BLK_SNAP_TRACKER_H
#include <linux/kref.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/rwsem.h>
#include <linux/blkdev.h>
#include <linux/fs.h>
#ifdef STANDALONE_BDEVFILTER
#include "bdevfilter.h"
#endif
struct cbt_map;
struct diff_area;
/**
* struct tracker - Tracker for a block device.
*
* @kref:
* Protects the structure from being released during processing of
* an ioctl.
* @link:
* List header.
* @dev_id:
* Original block device ID.
* @snapshot_is_taken:
* Indicates that a snapshot was taken for the device whose bios are
* handled by this tracker.
* @cbt_map:
* Pointer to a change block tracker map.
* @diff_area:
* Pointer to a difference area.
*
* The main goal of the tracker is to handle bios. The tracker detectes
* the range of sectors that will change and transmits them to the CBT map
* and to the difference area.
*/
struct tracker {
struct bdev_filter flt;
struct list_head link;
dev_t dev_id;
struct percpu_rw_semaphore submit_lock;
atomic_t snapshot_is_taken;
uuid_t owner_id;
struct cbt_map *cbt_map;
struct diff_area *diff_area;
};
void tracker_lock(void);
void tracker_unlock(void);
static inline void tracker_put(struct tracker *tracker)
{
if (likely(tracker))
bdev_filter_put(&tracker->flt);
};
struct tracker *tracker_get_by_dev(struct block_device *bdev);
int tracker_init(void);
void tracker_done(void);
struct tracker *tracker_create_or_get(dev_t dev_id, const uuid_t* owner_id);
int tracker_remove(dev_t dev_id);
int tracker_collect(int max_count, struct blk_snap_cbt_info *cbt_info,
int *pcount);
int tracker_read_cbt_bitmap(dev_t dev_id, unsigned int offset, size_t length,
char __user *user_buff);
int tracker_mark_dirty_blocks(dev_t dev_id,
struct blk_snap_block_range *block_ranges,
unsigned int count);
int tracker_take_snapshot(struct tracker *tracker);
void tracker_release_snapshot(struct tracker *tracker);
#if defined(HAVE_SUPER_BLOCK_FREEZE)
static inline int _freeze_bdev(struct block_device *bdev,
struct super_block **psuperblock)
{
struct super_block *superblock;
pr_debug("Freezing device [%u:%u]\n", MAJOR(bdev->bd_dev),
MINOR(bdev->bd_dev));
if (bdev->bd_super == NULL) {
pr_warn("Unable to freeze device [%u:%u]: no superblock was found\n",
MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
return 0;
}
superblock = freeze_bdev(bdev);
if (IS_ERR_OR_NULL(superblock)) {
int result;
pr_err("Failed to freeze device [%u:%u]\n", MAJOR(bdev->bd_dev),
MINOR(bdev->bd_dev));
if (superblock == NULL)
result = -ENODEV;
else {
result = PTR_ERR(superblock);
pr_err("Error code: %d\n", result);
}
return result;
}
pr_debug("Device [%u:%u] was frozen\n", MAJOR(bdev->bd_dev),
MINOR(bdev->bd_dev));
*psuperblock = superblock;
return 0;
}
static inline void _thaw_bdev(struct block_device *bdev,
struct super_block *superblock)
{
if (superblock == NULL)
return;
if (thaw_bdev(bdev, superblock))
pr_err("Failed to unfreeze device [%u:%u]\n",
MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
else
pr_debug("Device [%u:%u] was unfrozen\n", MAJOR(bdev->bd_dev),
MINOR(bdev->bd_dev));
}
#endif
#endif /* __BLK_SNAP_TRACKER_H */