#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
#endif
+#define DEFAULT_CHUNK 512
#define DEFAULT_BITMAP_CHUNK 4096
#define DEFAULT_BITMAP_DELAY 5
#define DEFAULT_MAX_WRITE_BEHIND 256
unsigned long long custom_array_size; /* size for non-default sized
* arrays (in sectors)
*/
+#define NO_RESHAPE 0
+#define VOLUME_RESHAPE 1
+#define CONTAINER_RESHAPE 2
int reshape_active;
unsigned long long reshape_progress;
+ int recovery_blocked; /* for external metadata it
+ * indicates that there is
+ * reshape in progress in
+ * container,
+ * for native metadata it is
+ * reshape_active field mirror
+ */
union {
unsigned long long resync_start; /* per-array resync position */
unsigned long long recovery_start; /* per-device rebuild position */
Help_manage[], Help_misc[], Help_monitor[], Help_config[];
/* for option that don't have short equivilents, we assign arbitrary
- * small numbers. '1' means an undecorated option, so we start at '2'.
- * (note we must stop before we get to 65 i.e. 'A')
+ * numbers later than any 'short' character option.
*/
enum special_options {
- AssumeClean = 2,
+ AssumeClean = 300,
BitmapChunk,
WriteBehind,
ReAdd,
NoDegraded,
Sparc22,
- BackupFile, /* 8 */
+ BackupFile,
HomeHost,
AutoHomeHost,
Symlinks,
Waitclean,
DetailPlatform,
KillSubarray,
- UpdateSubarray, /* 16 */
+ UpdateSubarray,
IncrementalPath,
- NoSharing
+ NoSharing,
+ HelpOptions,
+ Brief,
+ ManageOpt,
+ Add,
+ Remove,
+ Fail,
+ MiscOpt,
+ WaitOpt,
+ ConfigFile,
+ ChunkSize,
+ WriteMostly,
+ Layout,
+ Auto,
+ Force,
+ SuperMinor,
+ EMail,
+ ProgramOpt,
+ Increment,
+ Fork,
+ Bitmap,
+ RebuildMapOpt,
+ InvalidBackup,
+ UdevRules,
+ FreezeReshape,
+ Continue,
};
/* structures read from config file */
/* List of device names - wildcards expanded */
struct mddev_dev {
char *devname;
- char disposition; /* 'a' for add, 'r' for remove, 'f' for fail.
+ int disposition; /* 'a' for add, 'r' for remove, 'f' for fail.
* Not set for names read from .config
*/
char writemostly; /* 1 for 'set writemostly', 2 for 'clear writemostly' */
int resync; /* 3 if check, 2 if reshape, 1 if resync, 0 if recovery */
int devcnt;
int raid_disks;
- int chunk_size;
char * metadata_version;
struct dev_member {
char *name;
extern void mdstat_wait_fd(int fd, const sigset_t *sigmask);
extern int mddev_busy(int devnum);
extern struct mdstat_ent *mdstat_by_component(char *name);
+extern struct mdstat_ent *mdstat_by_subdev(char *subdev, int container);
struct map_ent {
struct map_ent *next;
int devnum, char *metadata, int uuid[4], char *path);
extern int map_lock(struct map_ent **melp);
extern void map_unlock(struct map_ent **melp);
+extern void map_fork(void);
/* various details can be requested */
enum sysfs_read_flags {
extern int sysfs_unique_holder(int devnum, long rdev);
extern int sysfs_freeze_array(struct mdinfo *sra);
extern int load_sys(char *path, char *buf);
-
+extern int reshape_prepare_fdlist(char *devname,
+ struct mdinfo *sra,
+ int raid_disks,
+ int nrdisks,
+ unsigned long blocks,
+ char *backup_file,
+ int *fdlist,
+ unsigned long long *offsets);
+extern void reshape_free_fdlist(int *fdlist,
+ unsigned long long *offsets,
+ int size);
+extern int reshape_open_backup_file(char *backup,
+ int fd,
+ char *devname,
+ long blocks,
+ int *fdlist,
+ unsigned long long *offsets,
+ int restart);
+extern unsigned long compute_backup_blocks(int nchunk, int ochunk,
+ unsigned int ndata, unsigned int odata);
extern int save_stripes(int *source, unsigned long long *offsets,
int raid_disks, int chunk_size, int level, int layout,
extern int restore_stripes(int *dest, unsigned long long *offsets,
int raid_disks, int chunk_size, int level, int layout,
int source, unsigned long long read_offset,
- unsigned long long start, unsigned long long length);
+ unsigned long long start, unsigned long long length,
+ char *src_buf);
#ifndef Sendmail
#define Sendmail "/usr/lib/sendmail -t"
struct active_array;
struct metadata_update;
+
+/* 'struct reshape' records the intermediate states
+ * a general reshape.
+ * The starting geometry is converted to the 'before' geometry
+ * by at most an atomic level change. They could be the same.
+ * Similarly the 'after' geometry is converted to the final
+ * geometry by at most a level change.
+ * Note that 'before' and 'after' must have the same level.
+ * 'blocks' is the minimum number of sectors for a reshape unit.
+ * This will be a multiple of the stripe size in each of the
+ * 'before' and 'after' geometries.
+ * If 'blocks' is 0, no restriping is necessary.
+ */
+struct reshape {
+ int level;
+ int parity; /* number of parity blocks/devices */
+ struct {
+ int layout;
+ int data_disks;
+ } before, after;
+ unsigned long long backup_blocks;
+ unsigned long long stripes; /* number of old stripes that comprise 'blocks'*/
+ unsigned long long new_size; /* New size of array in sectors */
+};
+
/* A superswitch provides entry point the a metadata handler.
*
* The super_switch primarily operates on some "metadata" that
* (raid_disk must already be set and correct) and it is filled
* with 1 for slots that are thought to be active and 0 for slots which
* appear to be failed/missing.
+ * *info is zeroed out before data is added.
*/
void (*getinfo_super)(struct supertype *st, struct mdinfo *info, char *map);
struct mdinfo *(*getinfo_super_disks)(struct supertype *st);
* linear-grow-new - add a new device to a linear array, but don't
* change the size: so superblock still matches
* linear-grow-update - now change the size of the array.
+ * writemostly - set the WriteMostly1 bit in the superblock devflags
+ * readwrite - clear the WriteMostly1 bit in the superblock devflags
*/
int (*update_super)(struct supertype *st, struct mdinfo *info,
char *update,
* when hot-adding a spare.
*/
int (*add_to_super)(struct supertype *st, mdu_disk_info_t *dinfo,
- int fd, char *devname);
+ int fd, char *devname);
+ /* update the metadata to delete a device,
+ * when hot-removing.
+ */
+ int (*remove_from_super)(struct supertype *st, mdu_disk_info_t *dinfo);
/* Write metadata to one device when fixing problems or adding
* a new device.
* added to validate changing size and new devices. If there are
* inter-device dependencies, it should record sufficient details
* so these can be validated.
- * Both 'size' and '*freesize' are in sectors. chunk is bytes.
+ * Both 'size' and '*freesize' are in sectors. chunk is KiB.
+ * Return value is:
+ * 1: everything is OK
+ * 0: not OK for some reason - if 'verbose', then error was reported.
+ * -1: st->sb was NULL, 'subdev' is a member of a container of this
+ * types, but array is not acceptable for some reason
+ * message was reported even if verbose is 0.
*/
int (*validate_geometry)(struct supertype *st, int level, int layout,
int raiddisks,
- int chunk, unsigned long long size,
+ int *chunk, unsigned long long size,
char *subdev, unsigned long long *freesize,
int verbose);
struct mdinfo *(*container_content)(struct supertype *st, char *subarray);
- /* Allow a metadata handler to override mdadm's default layouts */
- int (*default_layout)(int level); /* optional */
- /* query the supertype for default chunk size */
- int (*default_chunk)(struct supertype *st); /* optional */
+ /* query the supertype for default geometry */
+ void (*default_geometry)(struct supertype *st, int *level, int *layout, int *chunk); /* optional */
/* Permit subarray's to be deleted from inactive containers */
int (*kill_subarray)(struct supertype *st); /* optional */
/* Permit subarray's to be modified */
int (*update_subarray)(struct supertype *st, char *subarray,
char *update, struct mddev_ident *ident); /* optional */
+ /* Check if reshape is supported for this external format.
+ * st is obtained from super_by_fd() where st->subarray[0] is
+ * initialized to indicate if reshape is being performed at the
+ * container or subarray level
+ */
+ int (*reshape_super)(struct supertype *st, long long size, int level,
+ int layout, int chunksize, int raid_disks,
+ int delta_disks, char *backup, char *dev,
+ int verbose); /* optional */
+ int (*manage_reshape)( /* optional */
+ int afd, struct mdinfo *sra, struct reshape *reshape,
+ struct supertype *st, unsigned long blocks,
+ int *fds, unsigned long long *offsets,
+ int dests, int *destfd, unsigned long long *destoffsets);
/* for mdmon */
int (*open_new)(struct supertype *c, struct active_array *a,
*/
const char *(*get_disk_controller_domain)(const char *path);
+ /* for external backup area */
+ int (*recover_backup)(struct supertype *st, struct mdinfo *info);
+
int swapuuid; /* true if uuid is bigending rather than hostendian */
int external;
const char *name; /* canonical metadata name */
int len;
char *buf;
void *space; /* allocated space that monitor will use */
+ void **space_list; /* list of allocated spaces that monitor can
+ * use or that it returned.
+ */
struct metadata_update *next;
};
int container_dev; /* devnum of container */
void *sb;
void *info;
-
+ int ignore_hw_compat; /* used to inform metadata handlers that it should ignore
+ HW/firmware related incompatability to load metadata.
+ Used when examining metadata to display content of disk
+ when user has no hw/firmare compatible system.
+ */
struct metadata_update *updates;
struct metadata_update **update_tail;
extern struct supertype *dup_super(struct supertype *st);
extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);
extern int must_be_container(int fd);
-extern int dev_size_from_id(unsigned id, unsigned long long *size);
+extern int dev_size_from_id(dev_t id, unsigned long long *size);
extern void get_one_disk(int mdfd, mdu_array_info_t *ainf,
mdu_disk_info_t *disk);
void wait_for(char *dev, int fd);
extern int Manage_runstop(char *devname, int fd, int runstop, int quiet);
extern int Manage_resize(char *devname, int fd, long long size, int raid_disks);
extern int Manage_subdevs(char *devname, int fd,
- struct mddev_dev *devlist, int verbose, int test);
+ struct mddev_dev *devlist, int verbose, int test,
+ char *update, int force);
extern int autodetect(void);
extern int Grow_Add_device(char *devname, int fd, char *newdev);
extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force);
extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
long long size,
- int level, char *layout_str, int chunksize, int raid_disks);
+ int level, char *layout_str, int chunksize, int raid_disks,
+ struct mddev_dev *devlist,
+ int assume_clean, int force);
extern int Grow_restart(struct supertype *st, struct mdinfo *info,
int *fdlist, int cnt, char *backup_file, int verbose);
extern int Grow_continue(int mdfd, struct supertype *st,
- struct mdinfo *info, char *backup_file);
+ struct mdinfo *info, char *backup_file,
+ int freeze_reshape);
+
+extern int restore_backup(struct supertype *st,
+ struct mdinfo *content,
+ int working_disks,
+ int spares,
+ char *backup_file,
+ int verbose);
+extern int Grow_continue_command(char *devname, int fd,
+ char *backup_file, int verbose);
extern int Assemble(struct supertype *st, char *mddev,
struct mddev_ident *ident,
- struct mddev_dev *devlist, char *backup_file,
+ struct mddev_dev *devlist,
+ char *backup_file, int invalid_backup,
int readonly, int runstop,
char *update, char *homehost, int require_homehost,
- int verbose, int force);
+ int verbose, int force, int freeze_reshape);
extern int Build(char *mddev, int chunk, int level, int layout,
int raiddisks, struct mddev_dev *devlist, int assume_clean,
extern int Incremental(char *devname, int verbose, int runstop,
struct supertype *st, char *homehost, int require_homehost,
- int autof);
+ int autof, int freeze_reshape);
extern void RebuildMap(void);
extern int IncrementalScan(int verbose);
extern int IncrementalRemove(char *devname, char *path, int verbose);
unsigned long long array_size,
int major);
extern int ExamineBitmap(char *filename, int brief, struct supertype *st);
+extern int Write_rules(char *rule_name);
extern int bitmap_update_uuid(int fd, int *uuid, int swap);
extern unsigned long bitmap_sectors(struct bitmap_super_s *bsb);
extern int check_ext2(int fd, char *name);
extern int check_reiser(int fd, char *name);
extern int check_raid(int fd, char *name);
-extern int check_partitions(int fd, char *dname, unsigned long long freesize);
+extern int check_partitions(int fd, char *dname,
+ unsigned long long freesize,
+ unsigned long long size);
extern int get_mdp_major(void);
extern int dev_open(char *dev, int flags);
extern int open_dev(int devnum);
+extern int open_dev_flags(int devnum, int flags);
extern int open_dev_excl(int devnum);
extern int is_standard(char *dev, int *nump);
extern int same_dev(char *one, char *two);
extern char *conf_line(FILE *file);
extern char *conf_word(FILE *file, int allow_key);
extern int conf_name_is_free(char *name);
+extern int conf_verify_devnames(struct mddev_ident *array_list);
extern int devname_matches(char *name, char *match);
-extern struct mddev_ident *conf_match(struct mdinfo *info, struct supertype *st);
+extern struct mddev_ident *conf_match(struct supertype *st,
+ struct mdinfo *info,
+ char *devname,
+ int verbose, int *rvp);
+extern int experimental(void);
extern void free_line(char *line);
extern int match_oneof(char *devices, char *devname);
extern void uuid_from_super(int uuid[4], mdp_super_t *super);
-extern const int uuid_match_any[4];
+extern const int uuid_zero[4];
extern int same_uuid(int a[4], int b[4], int swapuuid);
extern void copy_uuid(void *a, int b[4], int swapuuid);
extern char *__fname_from_uuid(int id[4], int swap, char *buf, char sep);
extern unsigned long long get_component_size(int fd);
extern void remove_partitions(int fd);
extern int test_partition(int fd);
+extern int test_partition_from_id(dev_t id);
+extern int get_data_disks(int level, int layout, int raid_disks);
extern unsigned long long calc_array_size(int level, int raid_disks, int layout,
int chunksize, unsigned long long devsize);
extern int flush_metadata_updates(struct supertype *st);
extern void append_metadata_update(struct supertype *st, void *buf, int len);
extern int assemble_container_content(struct supertype *st, int mdfd,
struct mdinfo *content, int runstop,
- char *chosen_name, int verbose);
-
+ char *chosen_name, int verbose,
+ char *backup_file, int freeze_reshape);
+extern struct mdinfo *container_choose_spares(struct supertype *st,
+ unsigned long long min_size,
+ struct domainlist *domlist,
+ char *spare_group,
+ const char *metadata, int get_one);
+extern int move_spare(char *from_devname, char *to_devname, dev_t devid);
extern int add_disk(int mdfd, struct supertype *st,
struct mdinfo *sra, struct mdinfo *info);
+extern int remove_disk(int mdfd, struct supertype *st,
+ struct mdinfo *sra, struct mdinfo *info);
extern int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info);
unsigned long long min_recovery_start(struct mdinfo *array);
extern int open_container(int fd);
extern int is_container_member(struct mdstat_ent *ent, char *devname);
extern int is_subarray_active(char *subarray, char *devname);
-int is_container_active(char *devname);
extern int open_subarray(char *dev, char *subarray, struct supertype *st, int quiet);
extern struct superswitch *version_to_superswitch(char *vers);
extern __u32 random32(void);
extern int start_mdmon(int devnum);
+extern int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
+ struct supertype *st, unsigned long stripes,
+ int *fds, unsigned long long *offsets,
+ int dests, int *destfd, unsigned long long *destoffsets);
+void abort_reshape(struct mdinfo *sra);
+
extern char *devnum2devname(int num);
+extern void fmt_devname(char *name, int num);
extern int devname2devnum(char *name);
extern int stat2devnum(struct stat *st);
extern int fd2devnum(int fd);
/* The version string for a 'subarray' (an array in a container)
* is
* /containername/componentname for normal read-write arrays
- * -containername/componentname for read-only arrays.
+ * -containername/componentname for arrays which mdmon must not
+ * reconfigure. They might be read-only
+ * or might be undergoing reshape etc.
* containername is e.g. md0, md_d1
* componentname is dependant on the metadata. e.g. '1' 'S1' ...
*/
#define PATH_MAX 4096
#endif
+#define PROCESS_DELAYED -2
+#define PROCESS_PENDING -3