/*
 * raidreconf.h: Headers, types and includes for the raidreconf program
 *
 */

#ifndef __RAIDRECONF_H
#define __RAIDRECONF_H

#include "common.h"
#include "parser.h"
#include "raid_io.h"
#include "raidlib.h"
#include "version.h"
#include <assert.h>
#include <popt.h>

#include <sys/mount.h>		/* for BLKGETSIZE */
#ifndef BLKGETSIZE
#include <linux/fs.h>		/* for BLKGETSIZE */
#endif
#include <sys/sysmacros.h>

#define EXTRA_CONSISTENCY_CHECKS

#ifndef BLOCK_SIZE
#define BLOCK_SIZE      1024
#endif

#ifndef BLKGETSIZE
#define BLKGETSIZE _IO(0x12, 96)	/* Return device size.  */
#endif

/* This is a magic number that must *not* be equal to any known RAID level */
#define RRC_SINGLE_DISK_LEVEL 86

typedef struct rrc_disk_t {
    int fd;
    unsigned long chunks;
    unsigned long blocks;
    unsigned long disk_id;
    unsigned long reconf_blocks;	/* initialized in run_reconfiguration() */
} rrc_disk_t;

extern int algorithm_check;

typedef enum { LDR_FAILED, LDR_INCOMPLETE, LDR_DONE } driver_status_t;
typedef struct level_driver_t {
    const char *(*initialize) (void *, md_cfg_entry_t *, rrc_disk_t *,
			       unsigned long *);
     driver_status_t(*request_blocks) (void *);
    const char *(*update_super) (void *);
    const char *(*map_global_to_local) (void *, unsigned long, int *,
					unsigned long *);
    unsigned long (*map_local_to_global) (void *, int, unsigned long);
    void (*free_blocks_above_gblock) (void *, unsigned long);
    void (*unfree_all_blocks) (void *);
    void *priv;
} level_driver_t;

level_driver_t *new_single_driver(void);
level_driver_t *new_raid0_driver(void);
level_driver_t *new_raid5_driver(void);

extern mdu_version_t ver;
extern int test;

/* Globals that must be set before we run the reconfiguration 
 */
extern level_driver_t *source_driver;
extern level_driver_t *sink_driver;
extern md_cfg_entry_t *old_md_cfg;
extern md_cfg_entry_t *new_md_cfg;
extern rrc_disk_t *old_rrc_cfg;
extern rrc_disk_t *new_rrc_cfg;
extern unsigned long source_blocks;

const char *run_reconfiguration(void);


/*
 * Utility routines
 */

void confirm(const char *);
void hash_progress(unsigned long, unsigned long);
int setup_disk_arrays(md_cfg_entry_t *, rrc_disk_t **, md_cfg_entry_t *,
		      rrc_disk_t **);
int raid_get_size(md_cfg_entry_t *, unsigned long *);

md_cfg_entry_t *setup_single_config(const char *);


#endif
