Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dm-path-selector.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003 Sistina Software.
3  * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
4  *
5  * Module Author: Heinz Mauelshagen
6  *
7  * This file is released under the GPL.
8  *
9  * Path selector registration.
10  */
11 
12 #include <linux/device-mapper.h>
13 #include <linux/module.h>
14 
15 #include "dm-path-selector.h"
16 
17 #include <linux/slab.h>
18 
19 struct ps_internal {
21  struct list_head list;
22 };
23 
24 #define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst)
25 
26 static LIST_HEAD(_path_selectors);
27 static DECLARE_RWSEM(_ps_lock);
28 
29 static struct ps_internal *__find_path_selector_type(const char *name)
30 {
31  struct ps_internal *psi;
32 
33  list_for_each_entry(psi, &_path_selectors, list) {
34  if (!strcmp(name, psi->pst.name))
35  return psi;
36  }
37 
38  return NULL;
39 }
40 
41 static struct ps_internal *get_path_selector(const char *name)
42 {
43  struct ps_internal *psi;
44 
45  down_read(&_ps_lock);
46  psi = __find_path_selector_type(name);
47  if (psi && !try_module_get(psi->pst.module))
48  psi = NULL;
49  up_read(&_ps_lock);
50 
51  return psi;
52 }
53 
54 struct path_selector_type *dm_get_path_selector(const char *name)
55 {
56  struct ps_internal *psi;
57 
58  if (!name)
59  return NULL;
60 
61  psi = get_path_selector(name);
62  if (!psi) {
63  request_module("dm-%s", name);
64  psi = get_path_selector(name);
65  }
66 
67  return psi ? &psi->pst : NULL;
68 }
69 
71 {
72  struct ps_internal *psi;
73 
74  if (!pst)
75  return;
76 
77  down_read(&_ps_lock);
78  psi = __find_path_selector_type(pst->name);
79  if (!psi)
80  goto out;
81 
82  module_put(psi->pst.module);
83 out:
84  up_read(&_ps_lock);
85 }
86 
87 static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst)
88 {
89  struct ps_internal *psi = kzalloc(sizeof(*psi), GFP_KERNEL);
90 
91  if (psi)
92  psi->pst = *pst;
93 
94  return psi;
95 }
96 
98 {
99  int r = 0;
100  struct ps_internal *psi = _alloc_path_selector(pst);
101 
102  if (!psi)
103  return -ENOMEM;
104 
105  down_write(&_ps_lock);
106 
107  if (__find_path_selector_type(pst->name)) {
108  kfree(psi);
109  r = -EEXIST;
110  } else
111  list_add(&psi->list, &_path_selectors);
112 
113  up_write(&_ps_lock);
114 
115  return r;
116 }
117 
119 {
120  struct ps_internal *psi;
121 
122  down_write(&_ps_lock);
123 
124  psi = __find_path_selector_type(pst->name);
125  if (!psi) {
126  up_write(&_ps_lock);
127  return -EINVAL;
128  }
129 
130  list_del(&psi->list);
131 
132  up_write(&_ps_lock);
133 
134  kfree(psi);
135 
136  return 0;
137 }
138