/* constant dm_target structures for error, zero, linear, stripes etc. */
struct dm_target {
       int (*init)(struct dm_table_entry *, int argc, char **argv);
       int (*destroy)(struct dm_table_entry *);
       int (*strategy)(struct dm_table_entry *, struct buf *);
       int (*upcall)(struct dm_table_entry *, struct buf *);

       SLIST_ENTRY(dm_target) next;
};


struct dm_table_entry {
       struct dm_dev *dm_dev;          /* backlink */
       uint64_t start;
       uint64_t length;

       struct dm_target *target;
       void *target_config;
       SLIST_ENTRY(dm_table_entry) next;
};
SLIST(dm_table, dm_table_entry);


struct dm_pdev {
       struct vnode *pdev_vnode;
       int refcnt;
       SLIST_ENTRY(dm_pdev) next_pdev;
};
SLIST(dm_pdevs, pm_pdev);


struct dm_dev {
       char name[DM_NAME_LEN];
       char uuid[DM_UUID_LEN];

       int minor;
       uint32_t flags;

       kmutex_t dev_mtx;
       uint32_t event_nr;
       uint32_t ref_cnt;

       struct dm_pdev pdevs;

       int cur_active_table;
       struct dm_table tables[2];

       struct dm_dev_list upcalls;
       SLIST_NEXT(dm_dev) next_upcall;

       SLIST_NEXT(dm_dev) next_devlist;
};
SLIST(dm_dev_list, dm_dev) dm_devs;


/* for zero,error : dm_target->target_config == NULL */
/* for linear : */
struct target_linear_config {
       struct dm_pdev *pdev;
       uint64_t offset;
};


/* for mirror : */
struct target_mirror_config {
       struct dm_pdev *orig;
       struct dm_pdev *copies[MAX_MIRROR_COPIES];

       /* copied blocks bitmaps administration etc*/
       struct dm_pdev *log_pdev;       /* for administration */
       uint64_t log_regionsize;        /* blocksize of mirror */

       /* list of parts that still need copied etc.; run length encoded? */
       ....
};


/* for snapshot : */
struct target_snapshot_config {
       struct dm_dev *orig;

       /* modified blocks bitmaps administration etc*/
       struct dm_pdev *log_pdev;
       uint64_t log_regionsize;
       /* list of sector renames to the log device */
       ...
};