// SPDX-License-Identifier: GPL-2.0-or-later
/*
drbd_actlog.c
This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
Copyright (C) 2003-2008, LINBIT Information Technologies GmbH.
Copyright (C) 2003-2008, Philipp Reisner <philipp.reisner@linbit.com>.
Copyright (C) 2003-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
*/
#include <linux/slab.h>
#include <linux/crc32c.h>
#include <linux/drbd.h>
#include <linux/drbd_limits.h>
#include "drbd_int.h"
enum al_transaction_types {
AL_TR_UPDATE = 0,
AL_TR_INITIALIZED = 0xffff
};
/* all fields on disc in big endian */
struct __packed al_transaction_on_disk {
/* don't we all like magic */
__be32 magic;
/* to identify the most recent transaction block
* in the on disk ring buffer */
__be32 tr_number;
/* checksum on the full 4k block, with this field set to 0. */
__be32 crc32c;
/* type of transaction, special transaction types like:
* purge-all, set-all-idle, set-all-active, ... to-be-defined
* see also enum al_transaction_types */
__be16 transaction_type;
/* we currently allow only a few thousand extents,
* so 16bit will be enough for the slot number. */
/* how many updates in this transaction */
__be16 n_updates;
/* maximum slot number, "al-extents" in drbd.conf speak.
* Having this in each transaction should make reconfiguration
* of that parameter easier. */
__be16 context_size;
/* slot number the context starts with */
__be16 context_start_slot_nr;
/* Some reserved bytes. Expected usage is a 64bit counter of
* sectors-written since device creation, and other data generation tag
* supporting usage */
__be32 __reserved[4];
/* --- 36 byte used --- */
/* Reserve space for up to AL_UPDATES_PER_TRANSACTION changes
* in one transaction, then use the remaining byte in the 4k block for
* context information. "Flexible" number of updates per transaction
* does not help, as we have to account for the case when all update
* slots are used anyways, so it would only complicate code without
* additional benefit.
*/
__be16 update_slot_nr[AL_UPDATES_PER_TRANSACTION];
/* but the extent number is 32bit, which at an extent size of 4 MiB
* allows to cover device sizes of up to 2**54 Byte (16 PiB) */
__be32 update_extent_nr[AL_UPDATES_PER_TRANSACTION];
/* --- 420 bytes used (36 + 64*6) --- */
/* 4096 - 420 = 3676 = 919 * 4 */
__be32 context[AL_CONTEXT_PER_TRANSACTION];
};
void *drbd_md_get_buffer(struct drbd_device *device, const char *intent)
{
int r;
wait_event(device->misc_wait,
(r = atomic_cmpxchg(&device->md_io.in_use, 0, 1)) == 0 ||
device->state.disk <= D_FAILED);
if (r)
return NULL;
device->md_io.current_use = intent;
device->md_io.start_jif = jiffies;
device->md_io.submit_jif = device->md_io.start_jif - 1;
return page_address(device->md_io.page);
}
void drbd_md_put_buffer(struct drbd_device *device)
{
if (atomic_dec_and_test(&device->md_io.in_use))
wake_up(&device->misc_wait);
}
void wait_until_done_or_force_detached(struct drbd_device *device, struct drbd_backing_dev *bdev,
unsigned int *done)
{
long dt;
rcu_read_lock();
dt = rcu_dereference(bdev->disk_conf)->disk_timeout;
rcu_read_unlock();
dt = dt * HZ / 10;
if (dt == 0)
dt = MAX_SCHEDULE_TIMEOUT;
dt = wait_event_timeout(device->misc_wait,
*done || test_bit(FORCE_DETACH, &device->flags), dt);
if (dt == 0) {
drbd_err(device, "meta-data IO operation timed out\n");
drbd_chk_io_error(device, 1, DRBD_FORCE_DETACH);
}
}
static int _drbd_md_sync_page_io(struct drbd_device *device,
struct drbd_backing_dev *bdev,
sector_t sector, enum req_op op)
{
struct bio *bio;
/* we do all our meta data IO in aligned 4k blocks. */
const int size = 4096;
int err;
blk_opf_t op_flags = 0;
device->md_io.done = 0;
device->md_io.error = -ENODEV;
if ((op == REQ_OP_WRITE) && !test_bit(MD_NO_FUA, &device->flags))
op_flags |= REQ_FUA | REQ_PREFLUSH;
op_flags