Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
0003  * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
0004  *
0005  * Device-mapper snapshot exception store.
0006  *
0007  * This file is released under the GPL.
0008  */
0009 
0010 #ifndef _LINUX_DM_EXCEPTION_STORE
0011 #define _LINUX_DM_EXCEPTION_STORE
0012 
0013 #include <linux/blkdev.h>
0014 #include <linux/list_bl.h>
0015 #include <linux/device-mapper.h>
0016 
0017 /*
0018  * The snapshot code deals with largish chunks of the disk at a
0019  * time. Typically 32k - 512k.
0020  */
0021 typedef sector_t chunk_t;
0022 
0023 /*
0024  * An exception is used where an old chunk of data has been
0025  * replaced by a new one.
0026  * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number
0027  * of chunks that follow contiguously.  Remaining bits hold the number of the
0028  * chunk within the device.
0029  */
0030 struct dm_exception {
0031     struct hlist_bl_node hash_list;
0032 
0033     chunk_t old_chunk;
0034     chunk_t new_chunk;
0035 };
0036 
0037 /*
0038  * Abstraction to handle the meta/layout of exception stores (the
0039  * COW device).
0040  */
0041 struct dm_exception_store;
0042 struct dm_exception_store_type {
0043     const char *name;
0044     struct module *module;
0045 
0046     int (*ctr) (struct dm_exception_store *store, char *options);
0047 
0048     /*
0049      * Destroys this object when you've finished with it.
0050      */
0051     void (*dtr) (struct dm_exception_store *store);
0052 
0053     /*
0054      * The target shouldn't read the COW device until this is
0055      * called.  As exceptions are read from the COW, they are
0056      * reported back via the callback.
0057      */
0058     int (*read_metadata) (struct dm_exception_store *store,
0059                   int (*callback)(void *callback_context,
0060                           chunk_t old, chunk_t new),
0061                   void *callback_context);
0062 
0063     /*
0064      * Find somewhere to store the next exception.
0065      */
0066     int (*prepare_exception) (struct dm_exception_store *store,
0067                   struct dm_exception *e);
0068 
0069     /*
0070      * Update the metadata with this exception.
0071      */
0072     void (*commit_exception) (struct dm_exception_store *store,
0073                   struct dm_exception *e, int valid,
0074                   void (*callback) (void *, int success),
0075                   void *callback_context);
0076 
0077     /*
0078      * Returns 0 if the exception store is empty.
0079      *
0080      * If there are exceptions still to be merged, sets
0081      * *last_old_chunk and *last_new_chunk to the most recent
0082      * still-to-be-merged chunk and returns the number of
0083      * consecutive previous ones.
0084      */
0085     int (*prepare_merge) (struct dm_exception_store *store,
0086                   chunk_t *last_old_chunk, chunk_t *last_new_chunk);
0087 
0088     /*
0089      * Clear the last n exceptions.
0090      * nr_merged must be <= the value returned by prepare_merge.
0091      */
0092     int (*commit_merge) (struct dm_exception_store *store, int nr_merged);
0093 
0094     /*
0095      * The snapshot is invalid, note this in the metadata.
0096      */
0097     void (*drop_snapshot) (struct dm_exception_store *store);
0098 
0099     unsigned (*status) (struct dm_exception_store *store,
0100                 status_type_t status, char *result,
0101                 unsigned maxlen);
0102 
0103     /*
0104      * Return how full the snapshot is.
0105      */
0106     void (*usage) (struct dm_exception_store *store,
0107                sector_t *total_sectors, sector_t *sectors_allocated,
0108                sector_t *metadata_sectors);
0109 
0110     /* For internal device-mapper use only. */
0111     struct list_head list;
0112 };
0113 
0114 struct dm_snapshot;
0115 
0116 struct dm_exception_store {
0117     struct dm_exception_store_type *type;
0118     struct dm_snapshot *snap;
0119 
0120     /* Size of data blocks saved - must be a power of 2 */
0121     unsigned chunk_size;
0122     unsigned chunk_mask;
0123     unsigned chunk_shift;
0124 
0125     void *context;
0126 
0127     bool userspace_supports_overflow;
0128 };
0129 
0130 /*
0131  * Obtain the origin or cow device used by a given snapshot.
0132  */
0133 struct dm_dev *dm_snap_origin(struct dm_snapshot *snap);
0134 struct dm_dev *dm_snap_cow(struct dm_snapshot *snap);
0135 
0136 /*
0137  * Funtions to manipulate consecutive chunks
0138  */
0139 #define DM_CHUNK_CONSECUTIVE_BITS 8
0140 #define DM_CHUNK_NUMBER_BITS 56
0141 
0142 static inline chunk_t dm_chunk_number(chunk_t chunk)
0143 {
0144     return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL);
0145 }
0146 
0147 static inline unsigned dm_consecutive_chunk_count(struct dm_exception *e)
0148 {
0149     return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
0150 }
0151 
0152 static inline void dm_consecutive_chunk_count_inc(struct dm_exception *e)
0153 {
0154     e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS);
0155 
0156     BUG_ON(!dm_consecutive_chunk_count(e));
0157 }
0158 
0159 static inline void dm_consecutive_chunk_count_dec(struct dm_exception *e)
0160 {
0161     BUG_ON(!dm_consecutive_chunk_count(e));
0162 
0163     e->new_chunk -= (1ULL << DM_CHUNK_NUMBER_BITS);
0164 }
0165 
0166 /*
0167  * Return the number of sectors in the device.
0168  */
0169 static inline sector_t get_dev_size(struct block_device *bdev)
0170 {
0171     return bdev_nr_sectors(bdev);
0172 }
0173 
0174 static inline chunk_t sector_to_chunk(struct dm_exception_store *store,
0175                       sector_t sector)
0176 {
0177     return sector >> store->chunk_shift;
0178 }
0179 
0180 int dm_exception_store_type_register(struct dm_exception_store_type *type);
0181 int dm_exception_store_type_unregister(struct dm_exception_store_type *type);
0182 
0183 int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
0184                       unsigned chunk_size,
0185                       char **error);
0186 
0187 int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
0188                   struct dm_snapshot *snap,
0189                   unsigned *args_used,
0190                   struct dm_exception_store **store);
0191 void dm_exception_store_destroy(struct dm_exception_store *store);
0192 
0193 int dm_exception_store_init(void);
0194 void dm_exception_store_exit(void);
0195 
0196 /*
0197  * Two exception store implementations.
0198  */
0199 int dm_persistent_snapshot_init(void);
0200 void dm_persistent_snapshot_exit(void);
0201 
0202 int dm_transient_snapshot_init(void);
0203 void dm_transient_snapshot_exit(void);
0204 
0205 #endif /* _LINUX_DM_EXCEPTION_STORE */