Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
0003  * Copyright (C) 2006-2008 Red Hat GmbH
0004  *
0005  * This file is released under the GPL.
0006  */
0007 
0008 #include "dm-exception-store.h"
0009 
0010 #include <linux/mm.h>
0011 #include <linux/pagemap.h>
0012 #include <linux/vmalloc.h>
0013 #include <linux/export.h>
0014 #include <linux/slab.h>
0015 #include <linux/dm-io.h>
0016 
0017 #define DM_MSG_PREFIX "transient snapshot"
0018 
0019 /*-----------------------------------------------------------------
0020  * Implementation of the store for non-persistent snapshots.
0021  *---------------------------------------------------------------*/
0022 struct transient_c {
0023     sector_t next_free;
0024 };
0025 
0026 static void transient_dtr(struct dm_exception_store *store)
0027 {
0028     kfree(store->context);
0029 }
0030 
0031 static int transient_read_metadata(struct dm_exception_store *store,
0032                    int (*callback)(void *callback_context,
0033                            chunk_t old, chunk_t new),
0034                    void *callback_context)
0035 {
0036     return 0;
0037 }
0038 
0039 static int transient_prepare_exception(struct dm_exception_store *store,
0040                        struct dm_exception *e)
0041 {
0042     struct transient_c *tc = store->context;
0043     sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev);
0044 
0045     if (size < (tc->next_free + store->chunk_size))
0046         return -1;
0047 
0048     e->new_chunk = sector_to_chunk(store, tc->next_free);
0049     tc->next_free += store->chunk_size;
0050 
0051     return 0;
0052 }
0053 
0054 static void transient_commit_exception(struct dm_exception_store *store,
0055                        struct dm_exception *e, int valid,
0056                        void (*callback) (void *, int success),
0057                        void *callback_context)
0058 {
0059     /* Just succeed */
0060     callback(callback_context, valid);
0061 }
0062 
0063 static void transient_usage(struct dm_exception_store *store,
0064                 sector_t *total_sectors,
0065                 sector_t *sectors_allocated,
0066                 sector_t *metadata_sectors)
0067 {
0068     *sectors_allocated = ((struct transient_c *) store->context)->next_free;
0069     *total_sectors = get_dev_size(dm_snap_cow(store->snap)->bdev);
0070     *metadata_sectors = 0;
0071 }
0072 
0073 static int transient_ctr(struct dm_exception_store *store, char *options)
0074 {
0075     struct transient_c *tc;
0076 
0077     tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
0078     if (!tc)
0079         return -ENOMEM;
0080 
0081     tc->next_free = 0;
0082     store->context = tc;
0083 
0084     return 0;
0085 }
0086 
0087 static unsigned transient_status(struct dm_exception_store *store,
0088                  status_type_t status, char *result,
0089                  unsigned maxlen)
0090 {
0091     unsigned sz = 0;
0092 
0093     switch (status) {
0094     case STATUSTYPE_INFO:
0095         break;
0096     case STATUSTYPE_TABLE:
0097         DMEMIT(" N %llu", (unsigned long long)store->chunk_size);
0098         break;
0099     case STATUSTYPE_IMA:
0100         *result = '\0';
0101         break;
0102     }
0103 
0104     return sz;
0105 }
0106 
0107 static struct dm_exception_store_type _transient_type = {
0108     .name = "transient",
0109     .module = THIS_MODULE,
0110     .ctr = transient_ctr,
0111     .dtr = transient_dtr,
0112     .read_metadata = transient_read_metadata,
0113     .prepare_exception = transient_prepare_exception,
0114     .commit_exception = transient_commit_exception,
0115     .usage = transient_usage,
0116     .status = transient_status,
0117 };
0118 
0119 static struct dm_exception_store_type _transient_compat_type = {
0120     .name = "N",
0121     .module = THIS_MODULE,
0122     .ctr = transient_ctr,
0123     .dtr = transient_dtr,
0124     .read_metadata = transient_read_metadata,
0125     .prepare_exception = transient_prepare_exception,
0126     .commit_exception = transient_commit_exception,
0127     .usage = transient_usage,
0128     .status = transient_status,
0129 };
0130 
0131 int dm_transient_snapshot_init(void)
0132 {
0133     int r;
0134 
0135     r = dm_exception_store_type_register(&_transient_type);
0136     if (r) {
0137         DMWARN("Unable to register transient exception store type");
0138         return r;
0139     }
0140 
0141     r = dm_exception_store_type_register(&_transient_compat_type);
0142     if (r) {
0143         DMWARN("Unable to register old-style transient "
0144                "exception store type");
0145         dm_exception_store_type_unregister(&_transient_type);
0146         return r;
0147     }
0148 
0149     return r;
0150 }
0151 
0152 void dm_transient_snapshot_exit(void)
0153 {
0154     dm_exception_store_type_unregister(&_transient_type);
0155     dm_exception_store_type_unregister(&_transient_compat_type);
0156 }