Blame view

drivers/md/dm-cache-policy.c 3.61 KB
c6b4fcbad   Joe Thornber   dm: add cache target
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  /*
   * Copyright (C) 2012 Red Hat. All rights reserved.
   *
   * This file is released under the GPL.
   */
  
  #include "dm-cache-policy-internal.h"
  #include "dm.h"
  
  #include <linux/module.h>
  #include <linux/slab.h>
  
  /*----------------------------------------------------------------*/
  
  #define DM_MSG_PREFIX "cache-policy"
  
  static DEFINE_SPINLOCK(register_lock);
  static LIST_HEAD(register_list);
  
  static struct dm_cache_policy_type *__find_policy(const char *name)
  {
  	struct dm_cache_policy_type *t;
  
  	list_for_each_entry(t, &register_list, list)
  		if (!strcmp(t->name, name))
  			return t;
  
  	return NULL;
  }
  
  static struct dm_cache_policy_type *__get_policy_once(const char *name)
  {
  	struct dm_cache_policy_type *t = __find_policy(name);
  
  	if (t && !try_module_get(t->owner)) {
  		DMWARN("couldn't get module %s", name);
  		t = ERR_PTR(-EINVAL);
  	}
  
  	return t;
  }
  
  static struct dm_cache_policy_type *get_policy_once(const char *name)
  {
  	struct dm_cache_policy_type *t;
  
  	spin_lock(&register_lock);
  	t = __get_policy_once(name);
  	spin_unlock(&register_lock);
  
  	return t;
  }
  
  static struct dm_cache_policy_type *get_policy(const char *name)
  {
  	struct dm_cache_policy_type *t;
  
  	t = get_policy_once(name);
  	if (IS_ERR(t))
  		return NULL;
  
  	if (t)
  		return t;
  
  	request_module("dm-cache-%s", name);
  
  	t = get_policy_once(name);
  	if (IS_ERR(t))
  		return NULL;
  
  	return t;
  }
  
  static void put_policy(struct dm_cache_policy_type *t)
  {
  	module_put(t->owner);
  }
  
  int dm_cache_policy_register(struct dm_cache_policy_type *type)
  {
  	int r;
  
  	/* One size fits all for now */
  	if (type->hint_size != 0 && type->hint_size != 4) {
  		DMWARN("hint size must be 0 or 4 but %llu supplied.", (unsigned long long) type->hint_size);
  		return -EINVAL;
  	}
  
  	spin_lock(&register_lock);
  	if (__find_policy(type->name)) {
  		DMWARN("attempt to register policy under duplicate name %s", type->name);
  		r = -EINVAL;
  	} else {
  		list_add(&type->list, &register_list);
  		r = 0;
  	}
  	spin_unlock(&register_lock);
  
  	return r;
  }
  EXPORT_SYMBOL_GPL(dm_cache_policy_register);
  
  void dm_cache_policy_unregister(struct dm_cache_policy_type *type)
  {
  	spin_lock(&register_lock);
  	list_del_init(&type->list);
  	spin_unlock(&register_lock);
  }
  EXPORT_SYMBOL_GPL(dm_cache_policy_unregister);
  
  struct dm_cache_policy *dm_cache_policy_create(const char *name,
  					       dm_cblock_t cache_size,
  					       sector_t origin_size,
  					       sector_t cache_block_size)
  {
  	struct dm_cache_policy *p = NULL;
  	struct dm_cache_policy_type *type;
  
  	type = get_policy(name);
  	if (!type) {
  		DMWARN("unknown policy type");
4cb3e1db2   Mikulas Patocka   dm cache: return ...
122
  		return ERR_PTR(-EINVAL);
c6b4fcbad   Joe Thornber   dm: add cache target
123
124
125
126
127
  	}
  
  	p = type->create(cache_size, origin_size, cache_block_size);
  	if (!p) {
  		put_policy(type);
4cb3e1db2   Mikulas Patocka   dm cache: return ...
128
  		return ERR_PTR(-ENOMEM);
c6b4fcbad   Joe Thornber   dm: add cache target
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  	}
  	p->private = type;
  
  	return p;
  }
  EXPORT_SYMBOL_GPL(dm_cache_policy_create);
  
  void dm_cache_policy_destroy(struct dm_cache_policy *p)
  {
  	struct dm_cache_policy_type *t = p->private;
  
  	p->destroy(p);
  	put_policy(t);
  }
  EXPORT_SYMBOL_GPL(dm_cache_policy_destroy);
  
  const char *dm_cache_policy_get_name(struct dm_cache_policy *p)
  {
  	struct dm_cache_policy_type *t = p->private;
2e68c4e6c   Mike Snitzer   dm cache: add pol...
148
149
150
  	/* if t->real is set then an alias was used (e.g. "default") */
  	if (t->real)
  		return t->real->name;
c6b4fcbad   Joe Thornber   dm: add cache target
151
152
153
  	return t->name;
  }
  EXPORT_SYMBOL_GPL(dm_cache_policy_get_name);
4e7f506f6   Mike Snitzer   dm cache: policy ...
154
155
156
157
158
159
160
  const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p)
  {
  	struct dm_cache_policy_type *t = p->private;
  
  	return t->version;
  }
  EXPORT_SYMBOL_GPL(dm_cache_policy_get_version);
c6b4fcbad   Joe Thornber   dm: add cache target
161
162
163
164
165
166
167
168
169
  size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p)
  {
  	struct dm_cache_policy_type *t = p->private;
  
  	return t->hint_size;
  }
  EXPORT_SYMBOL_GPL(dm_cache_policy_get_hint_size);
  
  /*----------------------------------------------------------------*/