// SPDX-License-Identifier: GPL-2.0-only/* * Copyright (C) 2010-2011 Neil Brown * Copyright (C) 2010-2018 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ #include <linux/slab.h>#include <linux/module.h> #include "md.h"#include "raid1.h"#include "raid5.h"#include "raid10.h"#include "md-bitmap.h" #include <linux/device-mapper.h> #define DM_MSG_PREFIX "raid"#define MAX_RAID_DEVICES 253 /* md-raid kernel limit */ /* * Minimum sectors of free reshape space per raid device */#define MIN_FREE_RESHAPE_SPACE to_sector(4*4096) /* * Minimum journal space 4 MiB in sectors. */#define MIN_RAID456_JOURNAL_SPACE (4*2048) static bool devices_handle_discard_safely; /* * The following flags are used by dm-raid to set up the array state. * They must be cleared before md_run is called. */#define FirstUse 10 /* rdev flag */ struct raid_dev { /* * Two DM devices, one to hold metadata and one to hold the * actual data/parity. The reason for this is to not confuse * ti->len and give more flexibility in altering size and * characteristics. * * While it is possible for this device to be associated * with a different physical device than the data_dev, it * is intended for it to be the same. * |--------- Physical Device ---------| * |- meta_dev -|------ data_dev ------| */ struct dm_dev *meta_dev; struct dm_dev *data_dev; struct md_rdev rdev;}; /* * Bits for establishing rs->ctr_flags * * 1 = no flag value * 2 = flag with value */#define __CTR_FLAG_SYNC 0 /* 1 */ /* Not with raid0! */#define __CTR_FLAG_NOSYNC 1 /* 1 */ /* Not with raid0! */#define __CTR_FLAG_REBUILD 2 /* 2 */ /* Not with raid0! */#define __CTR_FLAG_DAEMON_SLEEP 3 /* 2 */ /* Not with raid0! */#define __CTR_FLAG_MIN_RECOVERY_RATE 4 /* 2 */ /* Not with raid0! */#define __CTR_FLAG_MAX_RECOVERY_RATE 5 /* 2 */ /* Not with raid0! */#define __CTR_FLAG_MAX_WRITE_BEHIND 6 /* 2 */ /* Only with raid1! */#define __CTR_FLAG_WRITE_MOSTLY 7 /* 2 */ /* Only with raid1! */#define __CTR_FLAG_STRIPE_CACHE 8 /* 2 */ /* Only with raid4/5/6! */#define __CTR_FLAG_REGION_SIZE 9 /* 2 */ /* Not with raid0! */#define __CTR_FLAG_RAID10_COPIES 10 /* 2 */ /* Only with raid10 */#define __CTR_FLAG_RAID10_FORMAT 11 /* 2 */ /* Only with raid10 *//* New for v1.9.0 */#define __CTR_FLAG_DELTA_DISKS 12 /* 2 */ /* Only with reshapable raid1/4/5/6/10! */#define __CTR_FLAG_DATA_OFFSET 13 /* 2 */ /* Only with reshapable raid4/5/6/10! */#define __CTR_FLAG_RAID10_USE_NEAR_SETS 14 /* 2 */ /* Only with raid10! */ /* New for v1.10.0 */#define __CTR_FLAG_JOURNAL_DEV 15 /* 2 */ /* Only with raid4/5/6 (journal device)! */ /* New for v1.11.1 */#define __CTR_FLAG_JOURNAL_MODE 16 /* 2 */ /* Only with raid4/5/6 (journal mode)! */ /* * Flags for rs->ctr_flags field. */#define CTR_FLAG_SYNC (1 << __CTR_FLAG_SYNC)#define CTR_FLAG_NOSYNC (1 << __CTR_FLAG_NOSYNC)#define CTR_FLAG_REBUILD (1 << __CTR_FLAG_REBUILD)#define CTR_FLAG_DAEMON_SLEEP (1 << __CTR_FLAG_DAEMON_SLEEP)#define CTR_FLAG_MIN_RECOVERY_RATE (1 << __CTR_FLAG_MIN_RECOVERY_RATE)#define CTR_FLAG_MAX_RECOVERY_RATE (1 << __CTR_FLAG_MAX_RECOVERY_RATE)#define CTR_FLAG_MAX_WRITE_BEHIND (1 << __CTR_FLAG_MAX_WRITE_BEHIND)#define CTR_FLAG_WRITE_MOSTLY (1 << __CTR_FLAG_WRITE_MOSTLY)#define CTR_FLAG_STRIPE_CACHE (1 << __CTR_FLAG_STRIPE_CACHE)#define CTR_FLAG_REGION_SIZE (1 << __CTR_FLAG_REGION_SIZE)#define CTR_FLAG_RAID10_COPIES (1 << __CTR_FLAG_RAID10_COPIES)#define CTR_FLAG_RAID10_FORMAT (1 << __CTR_FLAG_RAID10_FORMAT)#define CTR_FLAG_DELTA_DISKS (1 << __CTR_FLAG_DELTA_DISKS)#define CTR_FLAG_DATA_OFFSET (1 << __CTR_FLAG_DATA_OFFSET)#define CTR_FLAG_RAID10_USE_NEAR_SETS (1 << __CTR_FLAG_RAID10_USE_NEAR_SETS)#define CTR_FLAG_JOURNAL_DEV (1 << __CTR_FLAG_JOURNAL_DEV)#define CTR_FLAG_JOURNAL_MODE (1 << __CTR_FLAG_JOURNAL_MODE) /* * Definitions of various constructor flags to * be used in checks of valid / invalid flags * per raid level. *//* Define all any sync flags */#define CTR_FLAGS_ANY_SYNC (CTR_FLAG_SYNC | CTR_FLAG_NOSYNC) /* Define flags for options without argument (e.g. 'nosync') */#define CTR_FLAG_OPTIONS_NO_ARGS (CTR_FLAGS_ANY_SYNC | \ CTR_FLAG_RAID10_USE_NEAR_SETS) /* Define flags for options with one argument (e.g. 'delta_disks +2') */#define CTR_FLAG_OPTIONS_ONE_ARG (CTR_FLAG_REBUILD | \ CTR_FLAG_WRITE_MOSTLY | \ CTR_FLAG_DAEMON_SLEEP | \ CTR_FLAG_MIN_RECOVERY_RATE | \ CTR_FLAG_MAX_RECOVERY_RATE | \ CTR_FLAG_MAX_WRITE_BEHIND | \ CTR_FLAG_STRIPE_CACHE | \ CTR_FLAG_REGION_SIZE | \ CTR_FLAG_RAID10_COPIES | \ CTR_FLAG_RAID10_FORMAT | \ CTR_FLAG_DELTA_DISKS | \ CTR_FLAG_DATA_OFFSET | \ CTR_FLAG_JOURNAL_DEV | \ CTR_FLAG_JOURNAL_MODE) /* Valid options definitions per raid level... */ /* "raid0" does only accept data offset */#define RAID0_VALID_FLAGS (CTR_FLAG_DATA_OFFSET) /* "raid1" does not accept stripe cache, data offset, delta_disks or any raid10 options */#define RAID1_VALID_FLAGS (CTR_FLAGS_ANY_SYNC | \ CTR_FLAG_REBUILD | \ CTR_FLAG_WRITE_MOSTLY | \ CTR_FLAG_DAEMON_SLEEP | \ CTR_FLAG_MIN_RECOVERY_RATE | \ CTR_FLAG_MAX_RECOVERY_RATE | \ CTR_FLAG_MAX_WRITE_BEHIND | \ CTR_FLAG_REGION_SIZE | \ CTR_FLAG_DELTA_DISKS | \ CTR_FLAG_DATA_OFFSET) /* "raid10" does not accept any raid1 or stripe cache options */#define RAID10_VALID_FLAGS (CTR_FLAGS_ANY_SYNC | \ CTR_FLAG_REBUILD | \ CTR_FLAG_DAEMON_SLEEP | \ CTR_FLAG_MIN_RECOVERY_RATE | \ CTR_FLAG_MAX_RECOVERY_RATE | \ CTR_FLAG_REGION_SIZE | \ CTR_FLAG_RAID10_COPIES | \ CTR_FLAG_RAID10_FORMAT | \ CTR_FLAG_DELTA_DISKS | \ CTR_FLAG_DATA_OFFSET | \ CTR_FLAG_RAID10_USE_NEAR_SETS) /* * "raid4/5/6" do not accept any raid1 or raid10 specific options * * "raid6" does not accept "nosync", because it is not guaranteed * that both parity and q-syndrome are being written properly with * any writes */#define RAID45_VALID_FLAGS (CTR_FLAGS_ANY_SYNC | \ CTR_FLAG_REBUILD | \ CTR_FLAG_DAEMON_SLEEP | \ CTR_FLAG_MIN_RECOVERY_RATE | \ CTR_FLAG_MAX_RECOVERY_RATE | \ CTR_FLAG_STRIPE_CACHE | \ CTR_FLAG_REGION_SIZE | \ CTR_FLAG_DELTA_DISKS | \ CTR_FLAG_DATA_OFFSET | \ CTR_FLAG_JOURNAL_DEV | \ CTR_FLAG_JOURNAL_MODE) #define RAID6_VALID_FLAGS (CTR_FLAG_SYNC | \ CTR_FLAG_REBUILD | \ CTR_FLAG_DAEMON_SLEEP | \ CTR_FLAG_MIN_RECOVERY_RATE | \ CTR_FLAG_MAX_RECOVERY_RATE | \ CTR_FLAG_STRIPE_CACHE | \ CTR_FLAG_REGION_SIZE | \ CTR_FLAG_DELTA_DISKS | \ CTR_FLAG_DATA_OFFSET | \ CTR_FLAG_JOURNAL_DEV | \ CTR_FLAG_JOURNAL_MODE)/* ...valid options definitions per raid level */ /* * Flags for rs->runtime_flags field * (RT_FLAG prefix meaning "runtime flag") * * These are all internal and used to define runtime state, * e.g. to prevent another resume from preresume processing * the raid set all over again. */#define RT_FLAG_RS_PRERESUMED 0#define RT_FLAG_RS_RESUMED 1#define RT_FLAG_RS_BITMAP_LOADED 2#define RT_FLAG_UPDATE_SBS 3#define RT_FLAG_RESHAPE_RS 4#define RT_FLAG_RS_SUSPENDED 5#define RT_FLAG_RS_IN_SYNC 6#define RT_FLAG_RS_RESYNCING 7#define RT_FLAG_RS_GROW 8#define RT_FLAG_RS_FROZEN 9 /* Array elements of 64 bit needed for rebuild/failed disk bits */#define DISKS_ARRAY_ELEMS ((MAX_RAID_DEVICES + (sizeof(uint64_t) * 8 - 1)) / sizeof(uint64_t) / 8) /* * raid set level, layout and chunk sectors backup/restore */struct rs_layout { int new_level; int new_layout; int new_chunk_sectors;}; struct raid_set { struct dm_target *ti; uint32_t stripe_cache_entries; unsigned long ctr_flags; unsigned long runtime_flags; uint64_t rebuild_disks[DISKS_ARRAY_ELEMS]; int raid_disks; int delta_disks; int data_offset; int raid10_copies; int requested_bitmap_chunk_sectors; struct mddev md; struct raid_type *raid_type; sector_t array_sectors; sector_t dev_sectors; /* Optional raid4/5/6 journal device */ struct journal_dev { struct dm_dev *dev; struct md_rdev rdev; int mode; } journal_dev; struct raid_dev dev[] __counted_by(raid_disks);}; static void rs_config_backup(struct raid_set *rs, struct rs_layout *l){ struct mddev *mddev = &rs->md; l->new_level = mddev->new_level; l->new_layout = mddev->new_layout; l->new_chunk_sectors = mddev->new_chunk_sectors;} static void rs_config_restore(struct raid_set *rs, struct rs_layout *l){ struct mddev *mddev = &rs->md; mddev->new_level = l->new_level; mddev->new_layout = l->new_layout; mddev->new_chunk_sectors = l->new_chunk_sectors;} /* raid10 algorithms (i.e. formats) */#define ALGORITHM_RAID10_DEFAULT 0#define ALGORITHM_RAID10_NEAR 1#define ALGORITHM_RAID10_OFFSET 2#define ALGORITHM_RAID10_FAR 3 /* Supported raid types and properties. */static struct raid_type { const char *name; /* RAID algorithm. */ const char *descr; /* Descriptor text for logging. */ const unsigned int parity_devs; /* # of parity devices. */ const unsigned int minimal_devs;/* minimal # of devices in set. */ const unsigned int level; /* RAID level. */ const unsigned int algorithm; /* RAID algorithm. */} raid_types[] = { {"raid0", "raid0 (striping)", 0, 2, 0, 0 /* NONE */}, {"raid1", "raid1 (mirroring)", 0, 2, 1, 0 /* NONE */}, {"raid10_far", "raid10 far (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_FAR}, {"raid10_offset", "raid10 offset (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_OFFSET}, {"raid10_near", "raid10 near (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_NEAR}, {"raid10", "raid10 (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_DEFAULT}, {"raid4", "raid4 (dedicated first parity disk)", 1, 2, 5, ALGORITHM_PARITY_0}, /* raid4 layout = raid5_0 */ {"raid5_n", "raid5 (dedicated last parity disk)", 1, 2, 5, ALGORITHM_PARITY_N}, {"raid5_ls", "raid5 (left symmetric)", 1, 2, 5, ALGORITHM_LEFT_SYMMETRIC}, {"raid5_rs", "raid5 (right symmetric)", 1, 2, 5, ALGORITHM_RIGHT_SYMMETRIC}, {"raid5_la", "raid5 (left asymmetric)", 1, 2, 5, ALGORITHM_LEFT_ASYMMETRIC}, {"raid5_ra", "raid5 (right asymmetric)", 1, 2, 5, ALGORITHM_RIGHT_ASYMMETRIC}, {"raid6_zr", "raid6 (zero restart)", 2, 4, 6, ALGORITHM_ROTATING_ZERO_RESTART}, {"raid6_nr", "raid6 (N restart)", 2, 4, 6, ALGORITHM_ROTATING_N_RESTART}, {"raid6_nc", "raid6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE}, {"raid6_n_6", "raid6 (dedicated parity/Q n/6)", 2, 4, 6, ALGORITHM_PARITY_N_6}, {"raid6_ls_6", "raid6 (left symmetric dedicated Q 6)", 2, 4, 6, ALGORITHM_LEFT_SYMMETRIC_6}, {"raid6_rs_6", "raid6 (right symmetric dedicated Q 6)", 2, 4, 6, ALGORITHM_RIGHT_SYMMETRIC_6}, {"raid6_la_6", "raid6 (left asymmetric dedicated Q 6)", 2, 4, 6, ALGORITHM_LEFT_ASYMMETRIC_6}, {"raid6_ra_6", "raid6 (right asymmetric dedicated Q 6)", 2, 4, 6, ALGORITHM_RIGHT_ASYMMETRIC_6}}; /* True, if @v is in inclusive range [@min, @max] */static bool __within_range(long v, long min, long max){ return v >= min && v <= max;} /* All table line arguments are defined here */static struct arg_name_flag { const unsigned long flag; const char *name;} __arg_name_flags[] = { { CTR_FLAG_SYNC, "sync"}, { CTR_FLAG_NOSYNC, "nosync"}, { CTR_FLAG_REBUILD, "rebuild"}, { CTR_FLAG_DAEMON_SLEEP, "daemon_sleep"}, { CTR_FLAG_MIN_RECOVERY_RATE, "min_recovery_rate"}, { CTR_FLAG_MAX_RECOVERY_RATE, "max_recovery_rate"}, { CTR_FLAG_MAX_WRITE_BEHIND, "max_write_behind"}, { CTR_FLAG_WRITE_MOSTLY, "write_mostly"}, { CTR_FLAG_STRIPE_CACHE, "stripe_cache"}, { CTR_FLAG_REGION_SIZE, "region_size"}, { CTR_FLAG_RAID10_COPIES, "raid10_copies"}, { CTR_FLAG_RAID10_FORMAT, "raid10_format"}, { CTR_FLAG_DATA_OFFSET, "data_offset"}, { CTR_FLAG_DELTA_DISKS, "delta_disks"}, { CTR_FLAG_RAID10_USE_NEAR_SETS, "raid10_use_near_sets"}, { CTR_FLAG_JOURNAL_DEV, "journal_dev" }, { CTR_FLAG_JOURNAL_MODE, "journal_mode" },}; /* Return argument name string for given @flag */static const char *dm_raid_arg_name_by_flag(const uint32_t flag){ if (hweight32(flag) == 1) { struct arg_name_flag *anf = __arg_name_flags + ARRAY_SIZE(__arg_name_flags); while (anf-- > __arg_name_flags) if (flag & anf->flag) return anf->name; } else DMERR("%s called with more than one flag!", __func__); return NULL;} /* Define correlation of raid456 journal cache modes and dm-raid target line parameters */static struct { const int mode; const char *param;} _raid456_journal_mode[] = { { R5C_JOURNAL_MODE_WRITE_THROUGH, "writethrough" }, { R5C_JOURNAL_MODE_WRITE_BACK, "writeback" }}; /* Return MD raid4/5/6 journal mode for dm @journal_mode one */static int dm_raid_journal_mode_to_md(const char *mode){ int m = ARRAY_SIZE(_raid456_journal_mode); while (m--) if (!strcasecmp(mode, _raid456_journal_mode[m].param)) return _raid456_journal_mode[m].mode; return -EINVAL;} /* Return dm-raid raid4/5/6 journal mode string for @mode */static const char *md_journal_mode_to_dm_raid(const int mode){ int m = ARRAY_SIZE(_raid456_journal_mode); while (m--) if (mode == _raid456_journal_mode[m].mode) return _raid456_journal_mode[m].param; return "unknown";} /* * Bool helpers to test for various raid levels of a raid set. * It's level as reported by the superblock rather than * the requested raid_type passed to the constructor. *//* Return true, if raid set in @rs is raid0 */static bool rs_is_raid0(struct raid_set *rs){ return !rs->md.level;} /* Return true, if raid set in @rs is raid1 */static bool rs_is_raid1(struct raid_set *rs){ return rs->md.level == 1;} /* Return true, if raid set in @rs is raid10 */static bool rs_is_raid10(struct raid_set *rs){ return rs->md.level == 10;} /* Return true, if raid set in @rs is level 6 */static bool rs_is_raid6(struct raid_set *rs){ return rs->md.level == 6;} /* Return true, if raid set in @rs is level 4, 5 or 6 */static bool rs_is_raid456(struct raid_set *rs){ return __within_range(rs->md.level, 4, 6);} /* Return true, if raid set in @rs is reshapable */static bool __is_raid10_far(int layout);static bool rs_is_reshapable(struct raid_set *rs){ return rs_is_raid456(rs) || (rs_is_raid10(rs) && !__is_raid10_far(rs->md.new_layout));} /* Return true, if raid set in @rs is recovering */static bool rs_is_recovering(struct raid_set *rs){ return rs->md.resync_offset < rs->md.dev_sectors;} /* Return true, if raid set in @rs is reshaping */static bool rs_is_reshaping(struct raid_set *rs){ return rs->md.reshape_position != MaxSector;} /* * bool helpers to test for various raid levels of a raid type @rt */ /* Return true, if raid type in @rt is raid0 */static bool rt_is_raid0(struct raid_type *rt){ return !rt->level;} /* Return true, if raid type in @rt is raid1 */static bool rt_is_raid1(struct raid_type *rt){ return rt->level == 1;} /* Return true, if raid type in @rt is raid10 */static bool rt_is_raid10(struct raid_type *rt){ return rt->level == 10;} /* Return true, if raid type in @rt is raid4/5 */static bool rt_is_raid45(struct raid_type *rt){ return __within_range(rt->level, 4, 5);} /* Return true, if raid type in @rt is raid6 */static bool rt_is_raid6(struct raid_type *rt){ return rt->level == 6;} /* Return true, if raid type in @rt is raid4/5/6 */static bool rt_is_raid456(struct raid_type *rt){ return __within_range(rt->level, 4, 6);}/* END: raid level bools */ /* Return valid ctr flags for the raid level of @rs */static unsigned long __valid_flags(struct raid_set *rs){ if (rt_is_raid0(rs->raid_type)) return RAID0_VALID_FLAGS; else if (rt_is_raid1(rs->raid_type)) return RAID1_VALID_FLAGS; else if (rt_is_raid10(rs->raid_type)) return RAID10_VALID_FLAGS; else if (rt_is_raid45(rs->raid_type))Lines 1–500 of 4182. Load more
// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2010-2011 Neil Brown * Copyright (C) 2010-2018 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ #include <linux/slab.h> #include <linux/module.h> #include "md.h" #include "raid1.h" #include "raid5.h" #include "raid10.h" #include "md-bitmap.h" #include <linux/device-mapper.h> #define DM_MSG_PREFIX "raid" #define MAX_RAID_DEVICES 253 /* md-raid kernel limit */ /* * Minimum sectors of free reshape space per raid device */ #define MIN_FREE_RESHAPE_SPACE to_sector(4*4096) /* * Minimum journal space 4 MiB in sectors. */ #define MIN_RAID456_JOURNAL_SPACE (4*2048) static bool devices_handle_discard_safely; /* * The following flags are used by dm-raid to set up the array state. * They must be cleared before md_run is called. */ #define FirstUse 10 /* rdev flag */ struct raid_dev { /* * Two DM devices, one to hold metadata and one to hold the * actual data/parity. The reason for this is to not confuse * ti->len and give more flexibility in altering size and * characteristics. * * While it is possible for this device to be associated * with a different physical device than the data_dev, it * is intended for it to be the same. * |--------- Physical Device ---------| * |- meta_dev -|------ data_dev ------| */ struct dm_dev *meta_dev; struct dm_dev *data_dev; struct md_rdev rdev; }; /* * Bits for establishing rs->ctr_flags * * 1 = no flag value * 2 = flag with value */ #define __CTR_FLAG_SYNC 0 /* 1 */ /* Not with raid0! */ #define __CTR_FLAG_NOSYNC 1 /* 1 */ /* Not with raid0! */ #define __CTR_FLAG_REBUILD 2 /* 2 */ /* Not with raid0! */ #define __CTR_FLAG_DAEMON_SLEEP 3 /* 2 */ /* Not with raid0! */ #define __CTR_FLAG_MIN_RECOVERY_RATE 4 /* 2 */ /* Not with raid0! */ #define __CTR_FLAG_MAX_RECOVERY_RATE 5 /* 2 */ /* Not with raid0! */ #define __CTR_FLAG_MAX_WRITE_BEHIND 6 /* 2 */ /* Only with raid1! */ #define __CTR_FLAG_WRITE_MOSTLY 7 /* 2 */ /* Only with raid1! */ #define __CTR_FLAG_STRIPE_CACHE 8 /* 2 */ /* Only with raid4/5/6! */ #define __CTR_FLAG_REGION_SIZE 9 /* 2 */ /* Not with raid0! */ #define __CTR_FLAG_RAID10_COPIES 10 /* 2 */ /* Only with raid10 */ #define __CTR_FLAG_RAID10_FORMAT 11 /* 2 */ /* Only with raid10 */ /* New for v1.9.0 */ #define __CTR_FLAG_DELTA_DISKS 12 /* 2 */ /* Only with reshapable raid1/4/5/6/10! */ #define __CTR_FLAG_DATA_OFFSET 13 /* 2 */ /* Only with reshapable raid4/5/6/10! */ #define __CTR_FLAG_RAID10_USE_NEAR_SETS 14 /* 2 */ /* Only with raid10! */ /* New for v1.10.0 */ #define __CTR_FLAG_JOURNAL_DEV 15 /* 2 */ /* Only with raid4/5/6 (journal device)! */ /* New for v1.11.1 */ #define __CTR_FLAG_JOURNAL_MODE 16 /* 2 */ /* Only with raid4/5/6 (journal mode)! */ /* * Flags for rs->ctr_flags field. */ #define CTR_FLAG_SYNC (1 << __CTR_FLAG_SYNC) #define CTR_FLAG_NOSYNC (1 << __CTR_FLAG_NOSYNC) #define CTR_FLAG_REBUILD (1 << __CTR_FLAG_REBUILD) #define CTR_FLAG_DAEMON_SLEEP (1 << __CTR_FLAG_DAEMON_SLEEP) #define CTR_FLAG_MIN_RECOVERY_RATE (1 << __CTR_FLAG_MIN_RECOVERY_RATE) #define CTR_FLAG_MAX_RECOVERY_RATE (1 << __CTR_FLAG_MAX_RECOVERY_RATE) #define CTR_FLAG_MAX_WRITE_BEHIND (1 << __CTR_FLAG_MAX_WRITE_BEHIND) #define CTR_FLAG_WRITE_MOSTLY (1 << __CTR_FLAG_WRITE_MOSTLY) #define CTR_FLAG_STRIPE_CACHE (1 << __CTR_FLAG_STRIPE_CACHE) #define CTR_FLAG_REGION_SIZE (1 << __CTR_FLAG_REGION_SIZE) #define CTR_FLAG_RAID10_COPIES (1 << __CTR_FLAG_RAID10_COPIES) #define CTR_FLAG_RAID10_FORMAT (1 << __CTR_FLAG_RAID10_FORMAT) #define CTR_FLAG_DELTA_DISKS (1 << __CTR_FLAG_DELTA_DISKS) #define CTR_FLAG_DATA_OFFSET (1 << __CTR_FLAG_DATA_OFFSET) #define CTR_FLAG_RAID10_USE_NEAR_SETS (1 << __CTR_FLAG_RAID10_USE_NEAR_SETS) #define CTR_FLAG_JOURNAL_DEV (1 << __CTR_FLAG_JOURNAL_DEV) #define CTR_FLAG_JOURNAL_MODE (1 << __CTR_FLAG_JOURNAL_MODE) /* * Definitions of various constructor flags to * be used in checks of valid / invalid flags * per raid level. */ /* Define all any sync flags */ #define CTR_FLAGS_ANY_SYNC (CTR_FLAG_SYNC | CTR_FLAG_NOSYNC) /* Define flags for options without argument (e.g. 'nosync') */ #define CTR_FLAG_OPTIONS_NO_ARGS (CTR_FLAGS_ANY_SYNC | \ CTR_FLAG_RAID10_USE_NEAR_SETS) /* Define flags for options with one argument (e.g. 'delta_disks +2') */ #define CTR_FLAG_OPTIONS_ONE_ARG (CTR_FLAG_REBUILD | \ CTR_FLAG_WRITE_MOSTLY | \ CTR_FLAG_DAEMON_SLEEP | \ CTR_FLAG_MIN_RECOVERY_RATE | \ CTR_FLAG_MAX_RECOVERY_RATE | \ CTR_FLAG_MAX_WRITE_BEHIND | \ CTR_FLAG_STRIPE_CACHE | \ CTR_FLAG_REGION_SIZE | \ CTR_FLAG_RAID10_COPIES | \ CTR_FLAG_RAID10_FORMAT | \ CTR_FLAG_DELTA_DISKS | \ CTR_FLAG_DATA_OFFSET | \ CTR_FLAG_JOURNAL_DEV | \ CTR_FLAG_JOURNAL_MODE) /* Valid options definitions per raid level... */ /* "raid0" does only accept data offset */ #define RAID0_VALID_FLAGS (CTR_FLAG_DATA_OFFSET) /* "raid1" does not accept stripe cache, data offset, delta_disks or any raid10 options */ #define RAID1_VALID_FLAGS (CTR_FLAGS_ANY_SYNC | \ CTR_FLAG_REBUILD | \ CTR_FLAG_WRITE_MOSTLY | \ CTR_FLAG_DAEMON_SLEEP | \ CTR_FLAG_MIN_RECOVERY_RATE | \ CTR_FLAG_MAX_RECOVERY_RATE | \ CTR_FLAG_MAX_WRITE_BEHIND | \ CTR_FLAG_REGION_SIZE | \ CTR_FLAG_DELTA_DISKS | \ CTR_FLAG_DATA_OFFSET) /* "raid10" does not accept any raid1 or stripe cache options */ #define RAID10_VALID_FLAGS (CTR_FLAGS_ANY_SYNC | \ CTR_FLAG_REBUILD | \ CTR_FLAG_DAEMON_SLEEP | \ CTR_FLAG_MIN_RECOVERY_RATE | \ CTR_FLAG_MAX_RECOVERY_RATE | \ CTR_FLAG_REGION_SIZE | \ CTR_FLAG_RAID10_COPIES | \ CTR_FLAG_RAID10_FORMAT | \ CTR_FLAG_DELTA_DISKS | \ CTR_FLAG_DATA_OFFSET | \ CTR_FLAG_RAID10_USE_NEAR_SETS) /* * "raid4/5/6" do not accept any raid1 or raid10 specific options * * "raid6" does not accept "nosync", because it is not guaranteed * that both parity and q-syndrome are being written properly with * any writes */ #define RAID45_VALID_FLAGS (CTR_FLAGS_ANY_SYNC | \ CTR_FLAG_REBUILD | \ CTR_FLAG_DAEMON_SLEEP | \ CTR_FLAG_MIN_RECOVERY_RATE | \ CTR_FLAG_MAX_RECOVERY_RATE | \ CTR_FLAG_STRIPE_CACHE | \ CTR_FLAG_REGION_SIZE | \ CTR_FLAG_DELTA_DISKS | \ CTR_FLAG_DATA_OFFSET | \ CTR_FLAG_JOURNAL_DEV | \ CTR_FLAG_JOURNAL_MODE) #define RAID6_VALID_FLAGS (CTR_FLAG_SYNC | \ CTR_FLAG_REBUILD | \ CTR_FLAG_DAEMON_SLEEP | \ CTR_FLAG_MIN_RECOVERY_RATE | \ CTR_FLAG_MAX_RECOVERY_RATE | \ CTR_FLAG_STRIPE_CACHE | \ CTR_FLAG_REGION_SIZE | \ CTR_FLAG_DELTA_DISKS | \ CTR_FLAG_DATA_OFFSET | \ CTR_FLAG_JOURNAL_DEV | \ CTR_FLAG_JOURNAL_MODE) /* ...valid options definitions per raid level */ /* * Flags for rs->runtime_flags field * (RT_FLAG prefix meaning "runtime flag") * * These are all internal and used to define runtime state, * e.g. to prevent another resume from preresume processing * the raid set all over again. */ #define RT_FLAG_RS_PRERESUMED 0 #define RT_FLAG_RS_RESUMED 1 #define RT_FLAG_RS_BITMAP_LOADED 2 #define RT_FLAG_UPDATE_SBS 3 #define RT_FLAG_RESHAPE_RS 4 #define RT_FLAG_RS_SUSPENDED 5 #define RT_FLAG_RS_IN_SYNC 6 #define RT_FLAG_RS_RESYNCING 7 #define RT_FLAG_RS_GROW 8 #define RT_FLAG_RS_FROZEN 9 /* Array elements of 64 bit needed for rebuild/failed disk bits */ #define DISKS_ARRAY_ELEMS ((MAX_RAID_DEVICES + (sizeof(uint64_t) * 8 - 1)) / sizeof(uint64_t) / 8) /* * raid set level, layout and chunk sectors backup/restore */ struct rs_layout { int new_level; int new_layout; int new_chunk_sectors; }; struct raid_set { struct dm_target *ti; uint32_t stripe_cache_entries; unsigned long ctr_flags; unsigned long runtime_flags; uint64_t rebuild_disks[DISKS_ARRAY_ELEMS]; int raid_disks; int delta_disks; int data_offset; int raid10_copies; int requested_bitmap_chunk_sectors; struct mddev md; struct raid_type *raid_type; sector_t array_sectors; sector_t dev_sectors; /* Optional raid4/5/6 journal device */ struct journal_dev { struct dm_dev *dev; struct md_rdev rdev; int mode; } journal_dev; struct raid_dev dev[] __counted_by(raid_disks); }; static void rs_config_backup(struct raid_set *rs, struct rs_layout *l) { struct mddev *mddev = &rs->md; l->new_level = mddev->new_level; l->new_layout = mddev->new_layout; l->new_chunk_sectors = mddev->new_chunk_sectors; } static void rs_config_restore(struct raid_set *rs, struct rs_layout *l) { struct mddev *mddev = &rs->md; mddev->new_level = l->new_level; mddev->new_layout = l->new_layout; mddev->new_chunk_sectors = l->new_chunk_sectors; } /* raid10 algorithms (i.e. formats) */ #define ALGORITHM_RAID10_DEFAULT 0 #define ALGORITHM_RAID10_NEAR 1 #define ALGORITHM_RAID10_OFFSET 2 #define ALGORITHM_RAID10_FAR 3 /* Supported raid types and properties. */ static struct raid_type { const char *name; /* RAID algorithm. */ const char *descr; /* Descriptor text for logging. */ const unsigned int parity_devs; /* # of parity devices. */ const unsigned int minimal_devs;/* minimal # of devices in set. */ const unsigned int level; /* RAID level. */ const unsigned int algorithm; /* RAID algorithm. */ } raid_types[] = { {"raid0", "raid0 (striping)", 0, 2, 0, 0 /* NONE */}, {"raid1", "raid1 (mirroring)", 0, 2, 1, 0 /* NONE */}, {"raid10_far", "raid10 far (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_FAR}, {"raid10_offset", "raid10 offset (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_OFFSET}, {"raid10_near", "raid10 near (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_NEAR}, {"raid10", "raid10 (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_DEFAULT}, {"raid4", "raid4 (dedicated first parity disk)", 1, 2, 5, ALGORITHM_PARITY_0}, /* raid4 layout = raid5_0 */ {"raid5_n", "raid5 (dedicated last parity disk)", 1, 2, 5, ALGORITHM_PARITY_N}, {"raid5_ls", "raid5 (left symmetric)", 1, 2, 5, ALGORITHM_LEFT_SYMMETRIC}, {"raid5_rs", "raid5 (right symmetric)", 1, 2, 5, ALGORITHM_RIGHT_SYMMETRIC}, {"raid5_la", "raid5 (left asymmetric)", 1, 2, 5, ALGORITHM_LEFT_ASYMMETRIC}, {"raid5_ra", "raid5 (right asymmetric)", 1, 2, 5, ALGORITHM_RIGHT_ASYMMETRIC}, {"raid6_zr", "raid6 (zero restart)", 2, 4, 6, ALGORITHM_ROTATING_ZERO_RESTART}, {"raid6_nr", "raid6 (N restart)", 2, 4, 6, ALGORITHM_ROTATING_N_RESTART}, {"raid6_nc", "raid6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE}, {"raid6_n_6", "raid6 (dedicated parity/Q n/6)", 2, 4, 6, ALGORITHM_PARITY_N_6}, {"raid6_ls_6", "raid6 (left symmetric dedicated Q 6)", 2, 4, 6, ALGORITHM_LEFT_SYMMETRIC_6}, {"raid6_rs_6", "raid6 (right symmetric dedicated Q 6)", 2, 4, 6, ALGORITHM_RIGHT_SYMMETRIC_6}, {"raid6_la_6", "raid6 (left asymmetric dedicated Q 6)", 2, 4, 6, ALGORITHM_LEFT_ASYMMETRIC_6}, {"raid6_ra_6", "raid6 (right asymmetric dedicated Q 6)", 2, 4, 6, ALGORITHM_RIGHT_ASYMMETRIC_6} }; /* True, if @v is in inclusive range [@min, @max] */ static bool __within_range(long v, long min, long max) { return v >= min && v <= max; } /* All table line arguments are defined here */ static struct arg_name_flag { const unsigned long flag; const char *name; } __arg_name_flags[] = { { CTR_FLAG_SYNC, "sync"}, { CTR_FLAG_NOSYNC, "nosync"}, { CTR_FLAG_REBUILD, "rebuild"}, { CTR_FLAG_DAEMON_SLEEP, "daemon_sleep"}, { CTR_FLAG_MIN_RECOVERY_RATE, "min_recovery_rate"}, { CTR_FLAG_MAX_RECOVERY_RATE, "max_recovery_rate"}, { CTR_FLAG_MAX_WRITE_BEHIND, "max_write_behind"}, { CTR_FLAG_WRITE_MOSTLY, "write_mostly"}, { CTR_FLAG_STRIPE_CACHE, "stripe_cache"}, { CTR_FLAG_REGION_SIZE, "region_size"}, { CTR_FLAG_RAID10_COPIES, "raid10_copies"}, { CTR_FLAG_RAID10_FORMAT, "raid10_format"}, { CTR_FLAG_DATA_OFFSET, "data_offset"}, { CTR_FLAG_DELTA_DISKS, "delta_disks"}, { CTR_FLAG_RAID10_USE_NEAR_SETS, "raid10_use_near_sets"}, { CTR_FLAG_JOURNAL_DEV, "journal_dev" }, { CTR_FLAG_JOURNAL_MODE, "journal_mode" }, }; /* Return argument name string for given @flag */ static const char *dm_raid_arg_name_by_flag(const uint32_t flag) { if (hweight32(flag) == 1) { struct arg_name_flag *anf = __arg_name_flags + ARRAY_SIZE(__arg_name_flags); while (anf-- > __arg_name_flags) if (flag & anf->flag) return anf->name; } else DMERR("%s called with more than one flag!", __func__); return NULL; } /* Define correlation of raid456 journal cache modes and dm-raid target line parameters */ static struct { const int mode; const char *param; } _raid456_journal_mode[] = { { R5C_JOURNAL_MODE_WRITE_THROUGH, "writethrough" }, { R5C_JOURNAL_MODE_WRITE_BACK, "writeback" } }; /* Return MD raid4/5/6 journal mode for dm @journal_mode one */ static int dm_raid_journal_mode_to_md(const char *mode) { int m = ARRAY_SIZE(_raid456_journal_mode); while (m--) if (!strcasecmp(mode, _raid456_journal_mode[m].param)) return _raid456_journal_mode[m].mode; return -EINVAL; } /* Return dm-raid raid4/5/6 journal mode string for @mode */ static const char *md_journal_mode_to_dm_raid(const int mode) { int m = ARRAY_SIZE(_raid456_journal_mode); while (m--) if (mode == _raid456_journal_mode[m].mode) return _raid456_journal_mode[m].param; return "unknown"; } /* * Bool helpers to test for various raid levels of a raid set. * It's level as reported by the superblock rather than * the requested raid_type passed to the constructor. */ /* Return true, if raid set in @rs is raid0 */ static bool rs_is_raid0(struct raid_set *rs) { return !rs->md.level; } /* Return true, if raid set in @rs is raid1 */ static bool rs_is_raid1(struct raid_set *rs) { return rs->md.level == 1; } /* Return true, if raid set in @rs is raid10 */ static bool rs_is_raid10(struct raid_set *rs) { return rs->md.level == 10; } /* Return true, if raid set in @rs is level 6 */ static bool rs_is_raid6(struct raid_set *rs) { return rs->md.level == 6; } /* Return true, if raid set in @rs is level 4, 5 or 6 */ static bool rs_is_raid456(struct raid_set *rs) { return __within_range(rs->md.level, 4, 6); } /* Return true, if raid set in @rs is reshapable */ static bool __is_raid10_far(int layout); static bool rs_is_reshapable(struct raid_set *rs) { return rs_is_raid456(rs) || (rs_is_raid10(rs) && !__is_raid10_far(rs->md.new_layout)); } /* Return true, if raid set in @rs is recovering */ static bool rs_is_recovering(struct raid_set *rs) { return rs->md.resync_offset < rs->md.dev_sectors; } /* Return true, if raid set in @rs is reshaping */ static bool rs_is_reshaping(struct raid_set *rs) { return rs->md.reshape_position != MaxSector; } /* * bool helpers to test for various raid levels of a raid type @rt */ /* Return true, if raid type in @rt is raid0 */ static bool rt_is_raid0(struct raid_type *rt) { return !rt->level; } /* Return true, if raid type in @rt is raid1 */ static bool rt_is_raid1(struct raid_type *rt) { return rt->level == 1; } /* Return true, if raid type in @rt is raid10 */ static bool rt_is_raid10(struct raid_type *rt) { return rt->level == 10; } /* Return true, if raid type in @rt is raid4/5 */ static bool rt_is_raid45(struct raid_type *rt) { return __within_range(rt->level, 4, 5); } /* Return true, if raid type in @rt is raid6 */ static bool rt_is_raid6(struct raid_type *rt) { return rt->level == 6; } /* Return true, if raid type in @rt is raid4/5/6 */ static bool rt_is_raid456(struct raid_type *rt) { return __within_range(rt->level, 4, 6); } /* END: raid level bools */ /* Return valid ctr flags for the raid level of @rs */ static unsigned long __valid_flags(struct raid_set *rs) { if (rt_is_raid0(rs->raid_type)) return RAID0_VALID_FLAGS; else if (rt_is_raid1(rs->raid_type)) return RAID1_VALID_FLAGS; else if (rt_is_raid10(rs->raid_type)) return RAID10_VALID_FLAGS; else if (rt_is_raid45(rs->raid_type))