#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
-#if !defined(__dietlibc__) && !defined(__KLIBC__)
+#ifdef __GLIBC__
extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
-#else
+#elif !defined(lseek64)
# if defined(__NO_STAT64) || __WORDSIZE != 32
# define lseek64 lseek
# endif
int uuid[4];
char name[33];
unsigned long long data_offset;
+ unsigned long long new_data_offset;
unsigned long long component_size; /* same as array.size, except in
* sectors and up to 64bits.
*/
#define NO_RESHAPE 0
#define VOLUME_RESHAPE 1
#define CONTAINER_RESHAPE 2
+#define RESHAPE_NO_BACKUP 16 /* Mask 'or'ed in */
int reshape_active;
unsigned long long reshape_progress;
int recovery_blocked; /* for external metadata it
* for native metadata it is
* reshape_active field mirror
*/
+ /* During reshape we can sometimes change the data_offset to avoid
+ * over-writing still-valid data. We need to know if there is space.
+ * So getinfo_super will fill in space_before and space_after in sectors.
+ * data_offset can be increased or decreased by this amount.
+ */
+ unsigned long long space_before, space_after;
union {
unsigned long long resync_start; /* per-array resync position */
unsigned long long recovery_start; /* per-device rebuild position */
int autof;
int mode;
int symlinks;
+ int names;
struct supertype *supertype;
};
Add,
Remove,
Fail,
+ Replace,
+ With,
MiscOpt,
WaitOpt,
ConfigFile,
OffRootOpt,
Prefer,
KillOpt,
+ DataOffset,
+ ExamineBB,
+ Dump,
+ Restore,
};
enum prefix_standard {
* Not set for names read from .config
*/
char writemostly; /* 1 for 'set writemostly', 2 for 'clear writemostly' */
- char used; /* set when used */
+ int used; /* set when used */
+ long long data_offset;
struct mddev_dev *next;
};
struct mdstat_ent {
char *dev;
- int devnum;
+ char devnm[32];
int active;
char *level;
char *pattern; /* U or up, _ for down */
extern void free_mdstat(struct mdstat_ent *ms);
extern void mdstat_wait(int seconds);
extern void mdstat_wait_fd(int fd, const sigset_t *sigmask);
-extern int mddev_busy(int devnum);
+extern int mddev_busy(char *devnm);
extern struct mdstat_ent *mdstat_by_component(char *name);
-extern struct mdstat_ent *mdstat_by_subdev(char *subdev, int container);
+extern struct mdstat_ent *mdstat_by_subdev(char *subdev, char *container);
struct map_ent {
struct map_ent *next;
- int devnum;
+ char devnm[32];
char metadata[20];
int uuid[4];
int bad;
char *path;
};
-extern int map_update(struct map_ent **mpp, int devnum, char *metadata,
+extern int map_update(struct map_ent **mpp, char *devnm, char *metadata,
int uuid[4], char *path);
-extern void map_remove(struct map_ent **map, int devnum);
+extern void map_remove(struct map_ent **map, char *devnm);
extern struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]);
-extern struct map_ent *map_by_devnum(struct map_ent **map, int devnum);
+extern struct map_ent *map_by_devnm(struct map_ent **map, char *devnm);
extern struct map_ent *map_by_name(struct map_ent **map, char *name);
extern void map_read(struct map_ent **melp);
extern int map_write(struct map_ent *mel);
-extern void map_delete(struct map_ent **mapp, int devnum);
+extern void map_delete(struct map_ent **mapp, char *devnm);
extern void map_free(struct map_ent *map);
extern void map_add(struct map_ent **melp,
- int devnum, char *metadata, int uuid[4], char *path);
+ char *devnm, 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);
};
/* If fd >= 0, get the array it is open on,
- * else use devnum. >=0 -> major9. <0.....
+ * else use devnm.
*/
-extern int sysfs_open(int devnum, char *devname, char *attr);
-extern void sysfs_init(struct mdinfo *mdi, int fd, int devnum);
+extern int sysfs_open(char *devnm, char *devname, char *attr);
+extern void sysfs_init(struct mdinfo *mdi, int fd, char *devnm);
extern void sysfs_free(struct mdinfo *sra);
-extern struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options);
+extern struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options);
extern int sysfs_attr_match(const char *attr, const char *str);
extern int sysfs_match_word(const char *word, char **list);
extern int sysfs_set_str(struct mdinfo *sra, struct mdinfo *dev,
extern int sysfs_set_array(struct mdinfo *info, int vers);
extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume);
extern int sysfs_disk_to_scsi_id(int fd, __u32 *id);
-extern int sysfs_unique_holder(int devnum, long rdev);
+extern int sysfs_unique_holder(char *devnm, 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 metadata_update;
-/* 'struct reshape' records the intermediate states
+/* 'struct reshape' records the intermediate states of
* a general reshape.
* The starting geometry is converted to the 'before' geometry
* by at most an atomic level change. They could be the same.
* 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.
+ * 'min_offset_change' is the minimum change to data_offset to
+ * allow the reshape to happen. It is at least the larger of
+ * the old and new chunk sizes, and typically the same as 'blocks'
+ * divided by number of data disks.
*/
struct reshape {
int level;
int data_disks;
} before, after;
unsigned long long backup_blocks;
+ unsigned long long min_offset_change;
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
+ * The superswitch primarily operates on some "metadata" that
* is accessed via the 'supertype'.
* This metadata has one of three possible sources.
* 1/ It is read from a single device. In this case it may not completely
void (*brief_examine_super)(struct supertype *st, int verbose);
void (*brief_examine_subarrays)(struct supertype *st, int verbose);
void (*export_examine_super)(struct supertype *st);
+ int (*examine_badblocks)(struct supertype *st, int fd, char *devname);
+ int (*copy_metadata)(struct supertype *st, int from, int to);
/* Used to report details of an active array.
* ->load_super was possibly given a 'component' string.
* 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
+ * no-bitmap - clear any record that a bitmap is present.
+ * bbl - add a bad-block-log if possible
+ * no-bbl - remove and bad-block-log is it is empty.
+ * revert-reshape - If a reshape is in progress, modify metadata so
+ * it will resume going in the opposite direction.
*/
int (*update_super)(struct supertype *st, struct mdinfo *info,
char *update,
*/
int (*init_super)(struct supertype *st, mdu_array_info_t *info,
unsigned long long size, char *name,
- char *homehost, int *uuid);
+ char *homehost, int *uuid,
+ unsigned long long data_offset);
/* update the metadata to include new device, either at create or
* 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,
+ unsigned long long data_offset);
/* update the metadata to delete a device,
* when hot-removing.
*/
/* Write all metadata for this array.
*/
int (*write_init_super)(struct supertype *st);
+ /* Check if metadata read from one device is compatible with an array,
+ * used when assembling an array, or pseudo-assembling was with
+ * "--examine --brief"
+ * If "st" has not yet been loaded the superblock from, "tst" is
+ * moved in, otherwise the superblock in 'st' is compared with
+ * 'tst'.
+ */
int (*compare_super)(struct supertype *st, struct supertype *tst);
+ /* Load metadata from a single device. If 'devname' is not NULL
+ * print error messages as appropriate */
int (*load_super)(struct supertype *st, int fd, char *devname);
+ /* 'fd' is a 'container' md array - load array metadata from the
+ * whole container.
+ */
int (*load_container)(struct supertype *st, int fd, char *devname);
+ /* If 'arg' is a valid name of this metadata type, allocate and
+ * return a 'supertype' for the particular minor version */
struct supertype * (*match_metadata_desc)(char *arg);
- __u64 (*avail_size)(struct supertype *st, __u64 size);
+ /* If a device has the given size, and the data_offset has been
+ * requested - work out how much space is available for data.
+ * This involves adjusting for reserved space (e.g. bitmaps)
+ * and for any rounding.
+ * 'mdadm' only calls this for existing arrays where a possible
+ * spare is being added. However some super-handlers call it
+ * internally from validate_geometry when creating an array.
+ */
+ __u64 (*avail_size)(struct supertype *st, __u64 size,
+ unsigned long long data_offset);
+ /* This is similar to 'avail_size' in purpose, but is used for
+ * containers for which there is no 'component size' to compare.
+ * This reports that whole-device size which is a minimum
+ */
unsigned long long (*min_acceptable_spare_size)(struct supertype *st);
+ /* Find somewhere to put a bitmap - possibly auto-size it - and
+ * update the metadata to record this. The array may be newly
+ * created, in which case data_size may be updated, or it might
+ * already exist. Metadata handler can know if init_super
+ * has been called, but not write_init_super.
+ */
int (*add_internal_bitmap)(struct supertype *st, int *chunkp,
int delay, int write_behind,
unsigned long long size, int may_change, int major);
+ /* Seek 'fd' to start of write-intent-bitmap. Must be an
+ * md-native format bitmap
+ */
void (*locate_bitmap)(struct supertype *st, int fd);
+ /* if add_internal_bitmap succeeded for existing array, this
+ * writes it out.
+ */
int (*write_bitmap)(struct supertype *st, int fd);
+ /* Free the superblock and any other allocated data */
void (*free_super)(struct supertype *st);
/* validate_geometry is called with an st returned by
* match_metadata_desc.
- * It should check that the geometry described in compatible with
+ * It should check that the geometry described is compatible with
* the metadata type. It will be called repeatedly as devices
* added to validate changing size and new devices. If there are
* inter-device dependencies, it should record sufficient details
* 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
+ * type, 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,
+ unsigned long long data_offset,
char *subdev, unsigned long long *freesize,
int verbose);
+ /* Return a linked list of 'mdinfo' structures for all arrays
+ * in the container. For non-containers, it is like
+ * getinfo_super with an allocated mdinfo.*/
struct mdinfo *(*container_content)(struct supertype *st, char *subarray);
/* query the supertype for default geometry */
void (*default_geometry)(struct supertype *st, int *level, int *layout, int *chunk); /* optional */
struct superswitch *ss;
int minor_version;
int max_devs;
- int container_dev; /* devnum of container */
+ char container_devnm[32]; /* devnm of container */
void *sb;
void *info;
+ void *other; /* Hack used to convert v0.90 to v1.0 */
+ unsigned long long devsize;
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
/* extra stuff used by mdmon */
struct active_array *arrays;
int sock; /* listen to external programs */
- int devnum;
- char *devname; /* e.g. md0. This appears in metadata_verison:
- * external:/md0/12
- */
+ char devnm[32]; /* e.g. md0. This appears in metadata_version:
+ * external:/md0/12
+ */
int devcnt;
int retry_soon;
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(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 struct dev_policy *path_policy(char *path, char *type);
extern struct dev_policy *disk_policy(struct mdinfo *disk);
-extern struct dev_policy *devnum_policy(int dev);
+extern struct dev_policy *devid_policy(int devid);
extern void dev_policy_free(struct dev_policy *p);
//extern void pol_new(struct dev_policy **pol, char *name, char *val, char *metadata);
const char *metadata);
extern struct domainlist *domain_from_array(struct mdinfo *mdi,
const char *metadata);
-extern void domainlist_add_dev(struct domainlist **dom, int devnum,
+extern void domainlist_add_dev(struct domainlist **dom, int devid,
const char *metadata);
extern void domain_free(struct domainlist *dl);
extern void domain_merge(struct domainlist **domp, struct dev_policy *pol,
struct context *c, struct shape *s);
extern int Grow_reshape(char *devname, int fd,
struct mddev_dev *devlist,
+ unsigned long long data_offset,
struct context *c, struct shape *s);
extern int Grow_restart(struct supertype *st, struct mdinfo *info,
int *fdlist, int cnt, char *backup_file, int verbose);
char *name, int *uuid,
int subdevs, struct mddev_dev *devlist,
struct shape *s,
- struct context *c);
+ struct context *c,
+ unsigned long long data_offset);
extern int Detail(char *dev, struct context *c);
extern int Detail_Platform(struct superswitch *ss, int scan, int verbose, int export, char *controller_path);
extern int Query(char *dev);
+extern int ExamineBadblocks(char *devname, int brief, struct supertype *forcest);
extern int Examine(struct mddev_dev *devlist, struct context *c,
struct supertype *forcest);
extern int Monitor(struct mddev_dev *devlist,
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 Dump_metadata(char *dev, char *dir, struct context *c,
+ struct supertype *st);
+extern int Restore_metadata(char *dev, char *dir, struct context *c,
+ struct supertype *st, int only);
extern int md_get_version(int fd);
extern int get_linux_version(void);
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 open_dev(char *devnm);
+extern int open_dev_flags(char *devnm, int flags);
+extern int open_dev_excl(char *devnm);
extern int is_standard(char *dev, int *nump);
extern int same_dev(char *one, char *two);
extern int compare_paths (char* path1,char* path2);
+extern void enable_fds(int devices);
extern int parse_auto(char *str, char *msg, int config);
extern struct mddev_ident *conf_get_ident(char *dev);
extern char *conf_word(FILE *file, int allow_key);
extern void print_quoted(char *str);
extern void print_escape(char *str);
+extern int use_udev(void);
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 char *human_size_brief(long long bytes, int prefix);
extern void print_r10_layout(int layout);
-#define NoMdDev (1<<23)
-extern int find_free_devnum(int use_partitions);
+extern char *find_free_devnm(int use_partitions);
extern void put_md_name(char *name);
-extern char *get_md_name(int dev);
+extern char *devid2devnm(int devid);
+extern int devnm2devid(char *devnm);
+extern char *get_md_name(char *devnm);
extern char DefaultConfFile[];
#define METADATA 3
extern int open_mddev(char *dev, int report_errors);
extern int open_container(int fd);
+extern int metadata_container_matches(char *metadata, char *devnm);
+extern int metadata_subdev_matches(char *metadata, char *devnm);
extern int is_container_member(struct mdstat_ent *ent, char *devname);
extern int is_subarray_active(char *subarray, char *devname);
extern int open_subarray(char *dev, char *subarray, struct supertype *st, int quiet);
extern struct superswitch *version_to_superswitch(char *vers);
-extern int mdmon_running(int devnum);
-extern int mdmon_pid(int devnum);
+extern int mdmon_running(char *devnm);
+extern int mdmon_pid(char *devnm);
extern int check_env(char *name);
extern __u32 random32(void);
-extern int start_mdmon(int devnum);
+extern int start_mdmon(char *devnm);
extern int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
struct supertype *st, unsigned long stripes,
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);
-
-static inline int dev2major(int d)
-{
- if (d >= 0)
- return MD_MAJOR;
- else
- return get_mdp_major();
-}
+void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0);
-static inline int dev2minor(int d)
-{
- if (d >= 0)
- return d;
- return (-1-d) << MdpMinorShift;
-}
+extern void fmt_devname(char *name, int num);
+extern char *stat2devnm(struct stat *st);
+extern char *fd2devnm(int fd);
#define _ROUND_UP(val, base) (((val) + (base) - 1) & ~(base - 1))
#define ROUND_UP(val, base) _ROUND_UP(val, (typeof(val))(base))
* a value for 'invalid'. Use '1'.
*/
#define INVALID_SECTORS 1
-
-extern int __offroot;
+/* And another special number needed for --data_offset=variable */
+#define VARIABLE_OFFSET 3