Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2003 Sistina Software.
0003  * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
0004  *
0005  * Module Author: Heinz Mauelshagen
0006  *
0007  * This file is released under the GPL.
0008  *
0009  * Path selector registration.
0010  */
0011 
0012 #include <linux/device-mapper.h>
0013 #include <linux/module.h>
0014 
0015 #include "dm-path-selector.h"
0016 
0017 #include <linux/slab.h>
0018 
0019 struct ps_internal {
0020     struct path_selector_type pst;
0021     struct list_head list;
0022 };
0023 
0024 #define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst)
0025 
0026 static LIST_HEAD(_path_selectors);
0027 static DECLARE_RWSEM(_ps_lock);
0028 
0029 static struct ps_internal *__find_path_selector_type(const char *name)
0030 {
0031     struct ps_internal *psi;
0032 
0033     list_for_each_entry(psi, &_path_selectors, list) {
0034         if (!strcmp(name, psi->pst.name))
0035             return psi;
0036     }
0037 
0038     return NULL;
0039 }
0040 
0041 static struct ps_internal *get_path_selector(const char *name)
0042 {
0043     struct ps_internal *psi;
0044 
0045     down_read(&_ps_lock);
0046     psi = __find_path_selector_type(name);
0047     if (psi && !try_module_get(psi->pst.module))
0048         psi = NULL;
0049     up_read(&_ps_lock);
0050 
0051     return psi;
0052 }
0053 
0054 struct path_selector_type *dm_get_path_selector(const char *name)
0055 {
0056     struct ps_internal *psi;
0057 
0058     if (!name)
0059         return NULL;
0060 
0061     psi = get_path_selector(name);
0062     if (!psi) {
0063         request_module("dm-%s", name);
0064         psi = get_path_selector(name);
0065     }
0066 
0067     return psi ? &psi->pst : NULL;
0068 }
0069 
0070 void dm_put_path_selector(struct path_selector_type *pst)
0071 {
0072     struct ps_internal *psi;
0073 
0074     if (!pst)
0075         return;
0076 
0077     down_read(&_ps_lock);
0078     psi = __find_path_selector_type(pst->name);
0079     if (!psi)
0080         goto out;
0081 
0082     module_put(psi->pst.module);
0083 out:
0084     up_read(&_ps_lock);
0085 }
0086 
0087 static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst)
0088 {
0089     struct ps_internal *psi = kzalloc(sizeof(*psi), GFP_KERNEL);
0090 
0091     if (psi)
0092         psi->pst = *pst;
0093 
0094     return psi;
0095 }
0096 
0097 int dm_register_path_selector(struct path_selector_type *pst)
0098 {
0099     int r = 0;
0100     struct ps_internal *psi = _alloc_path_selector(pst);
0101 
0102     if (!psi)
0103         return -ENOMEM;
0104 
0105     down_write(&_ps_lock);
0106 
0107     if (__find_path_selector_type(pst->name)) {
0108         kfree(psi);
0109         r = -EEXIST;
0110     } else
0111         list_add(&psi->list, &_path_selectors);
0112 
0113     up_write(&_ps_lock);
0114 
0115     return r;
0116 }
0117 
0118 int dm_unregister_path_selector(struct path_selector_type *pst)
0119 {
0120     struct ps_internal *psi;
0121 
0122     down_write(&_ps_lock);
0123 
0124     psi = __find_path_selector_type(pst->name);
0125     if (!psi) {
0126         up_write(&_ps_lock);
0127         return -EINVAL;
0128     }
0129 
0130     list_del(&psi->list);
0131 
0132     up_write(&_ps_lock);
0133 
0134     kfree(psi);
0135 
0136     return 0;
0137 }
0138 
0139 EXPORT_SYMBOL_GPL(dm_register_path_selector);
0140 EXPORT_SYMBOL_GPL(dm_unregister_path_selector);