Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2a06c38 authored by NeilBrown's avatar NeilBrown
Browse files

Merge branch 'md-next' of git://github.com/goldwynr/linux into for-next

md-cluster: A better way for METADATA_UPDATED processing

The processing of METADATA_UPDATED message is too simple and prone to
errors. Besides, it would not update the internal data structures as
required.

This set of patches reads the superblock from one of the device of the MD
and checks for changes in the in-memory data structures. If there is a change,
it performs the necessary actions to keep the internal data structures
as it would be in the primary node.

An example is if a devices turns faulty. The algorithm is:

1. The initiator node marks the device as faulty and updates the superblock
2. The initiator node sends METADATA_UPDATED with an advisory  device number to the rest of the nodes.
3. The receiving node on receiving the METADATA_UPDATED message
  3.1 Reads the superblock
  3.2 Detects a device has failed by comparing with memory structure
  3.3 Calls the necessary functions to record the failure and get the device out of the active array.
  3.4 Acknowledges the message.

The patch series also fixes adding the disk which was impacted because of
the changes.

Patches can also be found at
https://github.com/goldwynr/linux branch md-next

Changes since V2:
 - Fix status synchrnoization after --add and --re-add operations
 - Included Guoqing's patches on endian correctness, zeroing cmsg etc
 - Restructure add_new_disk() and cancel()
parents 25cb62b7 23b63f9f
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -613,12 +613,10 @@ static int bitmap_read_sb(struct bitmap *bitmap)
	daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
	write_behind = le32_to_cpu(sb->write_behind);
	sectors_reserved = le32_to_cpu(sb->sectors_reserved);
	/* XXX: This is a hack to ensure that we don't use clustering
	 *  in case:
	 *	- dm-raid is in use and
	 *	- the nodes written in bitmap_sb is erroneous.
	/* Setup nodes/clustername only if bitmap version is
	 * cluster-compatible
	 */
	if (!bitmap->mddev->sync_super) {
	if (sb->version == cpu_to_le32(BITMAP_MAJOR_CLUSTERED)) {
		nodes = le32_to_cpu(sb->nodes);
		strlcpy(bitmap->mddev->bitmap_info.cluster_name,
				sb->cluster_name, 64);
@@ -628,7 +626,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
	if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
		reason = "bad magic";
	else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO ||
		 le32_to_cpu(sb->version) > BITMAP_MAJOR_HI)
		 le32_to_cpu(sb->version) > BITMAP_MAJOR_CLUSTERED)
		reason = "unrecognized superblock version";
	else if (chunksize < 512)
		reason = "bitmap chunksize too small";
@@ -1572,7 +1570,7 @@ void bitmap_close_sync(struct bitmap *bitmap)
}
EXPORT_SYMBOL(bitmap_close_sync);

void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)
void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force)
{
	sector_t s = 0;
	sector_t blocks;
@@ -1583,7 +1581,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)
		bitmap->last_end_sync = jiffies;
		return;
	}
	if (time_before(jiffies, (bitmap->last_end_sync
	if (!force && time_before(jiffies, (bitmap->last_end_sync
				  + bitmap->mddev->bitmap_info.daemon_sleep)))
		return;
	wait_event(bitmap->mddev->recovery_wait,
+3 −1
Original line number Diff line number Diff line
@@ -9,8 +9,10 @@
#define BITMAP_MAJOR_LO 3
/* version 4 insists the bitmap is in little-endian order
 * with version 3, it is host-endian which is non-portable
 * Version 5 is currently set only for clustered devices
 */
#define BITMAP_MAJOR_HI 4
#define BITMAP_MAJOR_CLUSTERED 5
#define	BITMAP_MAJOR_HOSTENDIAN 3

/*
@@ -255,7 +257,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset,
int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int degraded);
void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int aborted);
void bitmap_close_sync(struct bitmap *bitmap);
void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector);
void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force);

void bitmap_unplug(struct bitmap *bitmap);
void bitmap_daemon_work(struct mddev *mddev);
+114 −84
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ struct dlm_lock_resource {
	struct completion completion; /* completion for synchronized locking */
	void (*bast)(void *arg, int mode); /* blocking AST function pointer*/
	struct mddev *mddev; /* pointing back to mddev. */
	int mode;
};

struct suspend_info {
@@ -55,6 +56,7 @@ struct md_cluster_info {
	struct completion completion;
	struct mutex sb_mutex;
	struct dlm_lock_resource *bitmap_lockres;
	struct dlm_lock_resource *resync_lockres;
	struct list_head suspend_list;
	spinlock_t suspend_lock;
	struct md_thread *recovery_thread;
@@ -106,6 +108,8 @@ static int dlm_lock_sync(struct dlm_lock_resource *res, int mode)
	if (ret)
		return ret;
	wait_for_completion(&res->completion);
	if (res->lksb.sb_status == 0)
		res->mode = mode;
	return res->lksb.sb_status;
}

@@ -127,6 +131,7 @@ static struct dlm_lock_resource *lockres_init(struct mddev *mddev,
	init_completion(&res->completion);
	res->ls = cinfo->lockspace;
	res->mddev = mddev;
	res->mode = DLM_LOCK_IV;
	namelen = strlen(name);
	res->name = kzalloc(namelen + 1, GFP_KERNEL);
	if (!res->name) {
@@ -358,29 +363,32 @@ static void __remove_suspend_info(struct md_cluster_info *cinfo, int slot)

	list_for_each_entry_safe(s, tmp, &cinfo->suspend_list, list)
		if (slot == s->slot) {
			pr_info("%s:%d Deleting suspend_info: %d\n",
					__func__, __LINE__, slot);
			list_del(&s->list);
			kfree(s);
			break;
		}
}

static void remove_suspend_info(struct md_cluster_info *cinfo, int slot)
static void remove_suspend_info(struct mddev *mddev, int slot)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;
	spin_lock_irq(&cinfo->suspend_lock);
	__remove_suspend_info(cinfo, slot);
	spin_unlock_irq(&cinfo->suspend_lock);
	mddev->pers->quiesce(mddev, 2);
}


static void process_suspend_info(struct md_cluster_info *cinfo,
static void process_suspend_info(struct mddev *mddev,
		int slot, sector_t lo, sector_t hi)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;
	struct suspend_info *s;

	if (!hi) {
		remove_suspend_info(cinfo, slot);
		remove_suspend_info(mddev, slot);
		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
		md_wakeup_thread(mddev->thread);
		return;
	}
	s = kzalloc(sizeof(struct suspend_info), GFP_KERNEL);
@@ -389,11 +397,14 @@ static void process_suspend_info(struct md_cluster_info *cinfo,
	s->slot = slot;
	s->lo = lo;
	s->hi = hi;
	mddev->pers->quiesce(mddev, 1);
	mddev->pers->quiesce(mddev, 0);
	spin_lock_irq(&cinfo->suspend_lock);
	/* Remove existing entry (if exists) before adding */
	__remove_suspend_info(cinfo, slot);
	list_add(&s->list, &cinfo->suspend_list);
	spin_unlock_irq(&cinfo->suspend_lock);
	mddev->pers->quiesce(mddev, 2);
}

static void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg)
@@ -407,7 +418,7 @@ static void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg)

	len = snprintf(disk_uuid, 64, "DEVICE_UUID=");
	sprintf(disk_uuid + len, "%pU", cmsg->uuid);
	snprintf(raid_slot, 16, "RAID_DISK=%d", cmsg->raid_slot);
	snprintf(raid_slot, 16, "RAID_DISK=%d", le32_to_cpu(cmsg->raid_slot));
	pr_info("%s:%d Sending kobject change with %s and %s\n", __func__, __LINE__, disk_uuid, raid_slot);
	init_completion(&cinfo->newdisk_completion);
	set_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state);
@@ -421,63 +432,57 @@ static void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg)
static void process_metadata_update(struct mddev *mddev, struct cluster_msg *msg)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;

	md_reload_sb(mddev);
	md_reload_sb(mddev, le32_to_cpu(msg->raid_slot));
	dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR);
}

static void process_remove_disk(struct mddev *mddev, struct cluster_msg *msg)
{
	struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev, msg->raid_slot);
	struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev,
						   le32_to_cpu(msg->raid_slot));

	if (rdev)
		md_kick_rdev_from_array(rdev);
	else
		pr_warn("%s: %d Could not find disk(%d) to REMOVE\n", __func__, __LINE__, msg->raid_slot);
		pr_warn("%s: %d Could not find disk(%d) to REMOVE\n",
			__func__, __LINE__, le32_to_cpu(msg->raid_slot));
}

static void process_readd_disk(struct mddev *mddev, struct cluster_msg *msg)
{
	struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev, msg->raid_slot);
	struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev,
						   le32_to_cpu(msg->raid_slot));

	if (rdev && test_bit(Faulty, &rdev->flags))
		clear_bit(Faulty, &rdev->flags);
	else
		pr_warn("%s: %d Could not find disk(%d) which is faulty", __func__, __LINE__, msg->raid_slot);
		pr_warn("%s: %d Could not find disk(%d) which is faulty",
			__func__, __LINE__, le32_to_cpu(msg->raid_slot));
}

static void process_recvd_msg(struct mddev *mddev, struct cluster_msg *msg)
{
	if (WARN(mddev->cluster_info->slot_number - 1 == le32_to_cpu(msg->slot),
		"node %d received it's own msg\n", le32_to_cpu(msg->slot)))
		return;
	switch (msg->type) {
	case METADATA_UPDATED:
		pr_info("%s: %d Received message: METADATA_UPDATE from %d\n",
			__func__, __LINE__, msg->slot);
		process_metadata_update(mddev, msg);
		break;
	case RESYNCING:
		pr_info("%s: %d Received message: RESYNCING from %d\n",
			__func__, __LINE__, msg->slot);
		process_suspend_info(mddev->cluster_info, msg->slot,
		process_suspend_info(mddev, msg->slot,
				msg->low, msg->high);
		break;
	case NEWDISK:
		pr_info("%s: %d Received message: NEWDISK from %d\n",
			__func__, __LINE__, msg->slot);
		process_add_new_disk(mddev, msg);
		break;
	case REMOVE:
		pr_info("%s: %d Received REMOVE from %d\n",
			__func__, __LINE__, msg->slot);
		process_remove_disk(mddev, msg);
		break;
	case RE_ADD:
		pr_info("%s: %d Received RE_ADD from %d\n",
			__func__, __LINE__, msg->slot);
		process_readd_disk(mddev, msg);
		break;
	case BITMAP_NEEDS_SYNC:
		pr_info("%s: %d Received BITMAP_NEEDS_SYNC from %d\n",
			__func__, __LINE__, msg->slot);
		__recover_slot(mddev, msg->slot);
		break;
	default:
@@ -528,11 +533,17 @@ static void recv_daemon(struct md_thread *thread)
/* lock_comm()
 * Takes the lock on the TOKEN lock resource so no other
 * node can communicate while the operation is underway.
 * If called again, and the TOKEN lock is alread in EX mode
 * return success. However, care must be taken that unlock_comm()
 * is called only once.
 */
static int lock_comm(struct md_cluster_info *cinfo)
{
	int error;

	if (cinfo->token_lockres->mode == DLM_LOCK_EX)
		return 0;

	error = dlm_lock_sync(cinfo->token_lockres, DLM_LOCK_EX);
	if (error)
		pr_err("md-cluster(%s:%d): failed to get EX on TOKEN (%d)\n",
@@ -542,6 +553,7 @@ static int lock_comm(struct md_cluster_info *cinfo)

static void unlock_comm(struct md_cluster_info *cinfo)
{
	WARN_ON(cinfo->token_lockres->mode != DLM_LOCK_EX);
	dlm_unlock_sync(cinfo->token_lockres);
}

@@ -753,6 +765,10 @@ static int join(struct mddev *mddev, int nodes)
		goto err;
	}

	cinfo->resync_lockres = lockres_init(mddev, "resync", NULL, 0);
	if (!cinfo->resync_lockres)
		goto err;

	ret = gather_all_resync_info(mddev, nodes);
	if (ret)
		goto err;
@@ -763,6 +779,7 @@ static int join(struct mddev *mddev, int nodes)
	lockres_free(cinfo->token_lockres);
	lockres_free(cinfo->ack_lockres);
	lockres_free(cinfo->no_new_dev_lockres);
	lockres_free(cinfo->resync_lockres);
	lockres_free(cinfo->bitmap_lockres);
	if (cinfo->lockspace)
		dlm_release_lockspace(cinfo->lockspace, 2);
@@ -771,12 +788,32 @@ static int join(struct mddev *mddev, int nodes)
	return ret;
}

static void resync_bitmap(struct mddev *mddev)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;
	struct cluster_msg cmsg = {0};
	int err;

	cmsg.type = cpu_to_le32(BITMAP_NEEDS_SYNC);
	err = sendmsg(cinfo, &cmsg);
	if (err)
		pr_err("%s:%d: failed to send BITMAP_NEEDS_SYNC message (%d)\n",
			__func__, __LINE__, err);
}

static int leave(struct mddev *mddev)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;

	if (!cinfo)
		return 0;

	/* BITMAP_NEEDS_SYNC message should be sent when node
	 * is leaving the cluster with dirty bitmap, also we
	 * can only deliver it when dlm connection is available */
	if (cinfo->slot_number > 0 && mddev->recovery_cp != MaxSector)
		resync_bitmap(mddev);

	md_unregister_thread(&cinfo->recovery_thread);
	md_unregister_thread(&cinfo->recv_thread);
	lockres_free(cinfo->message_lockres);
@@ -799,15 +836,6 @@ static int slot_number(struct mddev *mddev)
	return cinfo->slot_number - 1;
}

static void resync_info_update(struct mddev *mddev, sector_t lo, sector_t hi)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;

	add_resync_info(mddev, cinfo->bitmap_lockres, lo, hi);
	/* Re-acquire the lock to refresh LVB */
	dlm_lock_sync(cinfo->bitmap_lockres, DLM_LOCK_PW);
}

static int metadata_update_start(struct mddev *mddev)
{
	return lock_comm(mddev->cluster_info);
@@ -817,59 +845,61 @@ static int metadata_update_finish(struct mddev *mddev)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;
	struct cluster_msg cmsg;
	int ret;
	struct md_rdev *rdev;
	int ret = 0;

	memset(&cmsg, 0, sizeof(cmsg));
	cmsg.type = cpu_to_le32(METADATA_UPDATED);
	cmsg.raid_slot = -1;
	/* Pick up a good active device number to send.
	 */
	rdev_for_each(rdev, mddev)
		if (rdev->raid_disk > -1 && !test_bit(Faulty, &rdev->flags)) {
			cmsg.raid_slot = cpu_to_le32(rdev->desc_nr);
			break;
		}
	if (cmsg.raid_slot >= 0)
		ret = __sendmsg(cinfo, &cmsg);
	else
		pr_warn("md-cluster: No good device id found to send\n");
	unlock_comm(cinfo);
	return ret;
}

static int metadata_update_cancel(struct mddev *mddev)
static void metadata_update_cancel(struct mddev *mddev)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;
	unlock_comm(cinfo);
}

	return dlm_unlock_sync(cinfo->token_lockres);
static int resync_start(struct mddev *mddev)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;
	cinfo->resync_lockres->flags |= DLM_LKF_NOQUEUE;
	return dlm_lock_sync(cinfo->resync_lockres, DLM_LOCK_EX);
}

static int resync_send(struct mddev *mddev, enum msg_type type,
		sector_t lo, sector_t hi)
static int resync_info_update(struct mddev *mddev, sector_t lo, sector_t hi)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;
	struct cluster_msg cmsg;
	int slot = cinfo->slot_number - 1;
	struct cluster_msg cmsg = {0};

	pr_info("%s:%d lo: %llu hi: %llu\n", __func__, __LINE__,
			(unsigned long long)lo,
			(unsigned long long)hi);
	resync_info_update(mddev, lo, hi);
	cmsg.type = cpu_to_le32(type);
	cmsg.slot = cpu_to_le32(slot);
	add_resync_info(mddev, cinfo->bitmap_lockres, lo, hi);
	/* Re-acquire the lock to refresh LVB */
	dlm_lock_sync(cinfo->bitmap_lockres, DLM_LOCK_PW);
	cmsg.type = cpu_to_le32(RESYNCING);
	cmsg.low = cpu_to_le64(lo);
	cmsg.high = cpu_to_le64(hi);
	return sendmsg(cinfo, &cmsg);
}

static int resync_start(struct mddev *mddev, sector_t lo, sector_t hi)
{
	pr_info("%s:%d\n", __func__, __LINE__);
	return resync_send(mddev, RESYNCING, lo, hi);
	return sendmsg(cinfo, &cmsg);
}

static void resync_finish(struct mddev *mddev)
static int resync_finish(struct mddev *mddev)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;
	struct cluster_msg cmsg;
	int slot = cinfo->slot_number - 1;

	pr_info("%s:%d\n", __func__, __LINE__);
	resync_send(mddev, RESYNCING, 0, 0);
	if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
		cmsg.type = cpu_to_le32(BITMAP_NEEDS_SYNC);
		cmsg.slot = cpu_to_le32(slot);
		sendmsg(cinfo, &cmsg);
	}
	cinfo->resync_lockres->flags &= ~DLM_LKF_NOQUEUE;
	dlm_unlock_sync(cinfo->resync_lockres);
	return resync_info_update(mddev, 0, 0);
}

static int area_resyncing(struct mddev *mddev, int direction,
@@ -896,7 +926,11 @@ static int area_resyncing(struct mddev *mddev, int direction,
	return ret;
}

static int add_new_disk_start(struct mddev *mddev, struct md_rdev *rdev)
/* add_new_disk() - initiates a disk add
 * However, if this fails before writing md_update_sb(),
 * add_new_disk_cancel() must be called to release token lock
 */
static int add_new_disk(struct mddev *mddev, struct md_rdev *rdev)
{
	struct md_cluster_info *cinfo = mddev->cluster_info;
	struct cluster_msg cmsg;
@@ -907,7 +941,7 @@ static int add_new_disk_start(struct mddev *mddev, struct md_rdev *rdev)
	memset(&cmsg, 0, sizeof(cmsg));
	cmsg.type = cpu_to_le32(NEWDISK);
	memcpy(cmsg.uuid, uuid, 16);
	cmsg.raid_slot = rdev->desc_nr;
	cmsg.raid_slot = cpu_to_le32(rdev->desc_nr);
	lock_comm(cinfo);
	ret = __sendmsg(cinfo, &cmsg);
	if (ret)
@@ -918,22 +952,17 @@ static int add_new_disk_start(struct mddev *mddev, struct md_rdev *rdev)
	/* Some node does not "see" the device */
	if (ret == -EAGAIN)
		ret = -ENOENT;
	if (ret)
		unlock_comm(cinfo);
	else
		dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR);
	return ret;
}

static int add_new_disk_finish(struct mddev *mddev)
static void add_new_disk_cancel(struct mddev *mddev)
{
	struct cluster_msg cmsg;
	struct md_cluster_info *cinfo = mddev->cluster_info;
	int ret;
	/* Write sb and inform others */
	md_update_sb(mddev, 1);
	cmsg.type = METADATA_UPDATED;
	ret = __sendmsg(cinfo, &cmsg);
	unlock_comm(cinfo);
	return ret;
}

static int new_disk_ack(struct mddev *mddev, bool ack)
@@ -953,10 +982,10 @@ static int new_disk_ack(struct mddev *mddev, bool ack)

static int remove_disk(struct mddev *mddev, struct md_rdev *rdev)
{
	struct cluster_msg cmsg;
	struct cluster_msg cmsg = {0};
	struct md_cluster_info *cinfo = mddev->cluster_info;
	cmsg.type = REMOVE;
	cmsg.raid_slot = rdev->desc_nr;
	cmsg.type = cpu_to_le32(REMOVE);
	cmsg.raid_slot = cpu_to_le32(rdev->desc_nr);
	return __sendmsg(cinfo, &cmsg);
}

@@ -964,12 +993,12 @@ static int gather_bitmaps(struct md_rdev *rdev)
{
	int sn, err;
	sector_t lo, hi;
	struct cluster_msg cmsg;
	struct cluster_msg cmsg = {0};
	struct mddev *mddev = rdev->mddev;
	struct md_cluster_info *cinfo = mddev->cluster_info;

	cmsg.type = RE_ADD;
	cmsg.raid_slot = rdev->desc_nr;
	cmsg.type = cpu_to_le32(RE_ADD);
	cmsg.raid_slot = cpu_to_le32(rdev->desc_nr);
	err = sendmsg(cinfo, &cmsg);
	if (err)
		goto out;
@@ -993,15 +1022,15 @@ static struct md_cluster_operations cluster_ops = {
	.join   = join,
	.leave  = leave,
	.slot_number = slot_number,
	.resync_info_update = resync_info_update,
	.resync_start = resync_start,
	.resync_finish = resync_finish,
	.resync_info_update = resync_info_update,
	.metadata_update_start = metadata_update_start,
	.metadata_update_finish = metadata_update_finish,
	.metadata_update_cancel = metadata_update_cancel,
	.area_resyncing = area_resyncing,
	.add_new_disk_start = add_new_disk_start,
	.add_new_disk_finish = add_new_disk_finish,
	.add_new_disk = add_new_disk,
	.add_new_disk_cancel = add_new_disk_cancel,
	.new_disk_ack = new_disk_ack,
	.remove_disk = remove_disk,
	.gather_bitmaps = gather_bitmaps,
@@ -1022,5 +1051,6 @@ static void cluster_exit(void)

module_init(cluster_init);
module_exit(cluster_exit);
MODULE_AUTHOR("SUSE");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Clustering support for MD");
+6 −6
Original line number Diff line number Diff line
@@ -12,15 +12,15 @@ struct md_cluster_operations {
	int (*join)(struct mddev *mddev, int nodes);
	int (*leave)(struct mddev *mddev);
	int (*slot_number)(struct mddev *mddev);
	void (*resync_info_update)(struct mddev *mddev, sector_t lo, sector_t hi);
	int (*resync_start)(struct mddev *mddev, sector_t lo, sector_t hi);
	void (*resync_finish)(struct mddev *mddev);
	int (*resync_info_update)(struct mddev *mddev, sector_t lo, sector_t hi);
	int (*metadata_update_start)(struct mddev *mddev);
	int (*metadata_update_finish)(struct mddev *mddev);
	int (*metadata_update_cancel)(struct mddev *mddev);
	void (*metadata_update_cancel)(struct mddev *mddev);
	int (*resync_start)(struct mddev *mddev);
	int (*resync_finish)(struct mddev *mddev);
	int (*area_resyncing)(struct mddev *mddev, int direction, sector_t lo, sector_t hi);
	int (*add_new_disk_start)(struct mddev *mddev, struct md_rdev *rdev);
	int (*add_new_disk_finish)(struct mddev *mddev);
	int (*add_new_disk)(struct mddev *mddev, struct md_rdev *rdev);
	void (*add_new_disk_cancel)(struct mddev *mddev);
	int (*new_disk_ack)(struct mddev *mddev, bool ack);
	int (*remove_disk)(struct mddev *mddev, struct md_rdev *rdev);
	int (*gather_bitmaps)(struct md_rdev *rdev);
+248 −111

File changed.

Preview size limit exceeded, changes collapsed.

Loading