Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 "dm.h"
 13 #include "dm-path-selector.h"
 14 
 15 #include <linux/slab.h>
 16 
 17 struct ps_internal {
 18         struct path_selector_type pst;
 19 
 20         struct list_head list;
 21         long use;
 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) {
 48                 if ((psi->use == 0) && !try_module_get(psi->pst.module))
 49                         psi = NULL;
 50                 else
 51                         psi->use++;
 52         }
 53         up_read(&_ps_lock);
 54 
 55         return psi;
 56 }
 57 
 58 struct path_selector_type *dm_get_path_selector(const char *name)
 59 {
 60         struct ps_internal *psi;
 61 
 62         if (!name)
 63                 return NULL;
 64 
 65         psi = get_path_selector(name);
 66         if (!psi) {
 67                 request_module("dm-%s", name);
 68                 psi = get_path_selector(name);
 69         }
 70 
 71         return psi ? &psi->pst : NULL;
 72 }
 73 
 74 void dm_put_path_selector(struct path_selector_type *pst)
 75 {
 76         struct ps_internal *psi;
 77 
 78         if (!pst)
 79                 return;
 80 
 81         down_read(&_ps_lock);
 82         psi = __find_path_selector_type(pst->name);
 83         if (!psi)
 84                 goto out;
 85 
 86         if (--psi->use == 0)
 87                 module_put(psi->pst.module);
 88 
 89         BUG_ON(psi->use < 0);
 90 
 91 out:
 92         up_read(&_ps_lock);
 93 }
 94 
 95 static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst)
 96 {
 97         struct ps_internal *psi = kzalloc(sizeof(*psi), GFP_KERNEL);
 98 
 99         if (psi)
100                 psi->pst = *pst;
101 
102         return psi;
103 }
104 
105 int dm_register_path_selector(struct path_selector_type *pst)
106 {
107         int r = 0;
108         struct ps_internal *psi = _alloc_path_selector(pst);
109 
110         if (!psi)
111                 return -ENOMEM;
112 
113         down_write(&_ps_lock);
114 
115         if (__find_path_selector_type(pst->name)) {
116                 kfree(psi);
117                 r = -EEXIST;
118         } else
119                 list_add(&psi->list, &_path_selectors);
120 
121         up_write(&_ps_lock);
122 
123         return r;
124 }
125 
126 int dm_unregister_path_selector(struct path_selector_type *pst)
127 {
128         struct ps_internal *psi;
129 
130         down_write(&_ps_lock);
131 
132         psi = __find_path_selector_type(pst->name);
133         if (!psi) {
134                 up_write(&_ps_lock);
135                 return -EINVAL;
136         }
137 
138         if (psi->use) {
139                 up_write(&_ps_lock);
140                 return -ETXTBSY;
141         }
142 
143         list_del(&psi->list);
144 
145         up_write(&_ps_lock);
146 
147         kfree(psi);
148 
149         return 0;
150 }
151 
152 EXPORT_SYMBOL_GPL(dm_register_path_selector);
153 EXPORT_SYMBOL_GPL(dm_unregister_path_selector);
154 
  This page was automatically generated by the LXR engine.