Whamcloud - gitweb
7ef83cea4534708b9af8301767bf4babcd5d7dde
[fs/lustre-release.git] / lustre / obdclass / lu_tgt_pool.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  */
31 /*
32  * lustre/target/tgt_pool.c
33  *
34  * This file handles creation, lookup, and removal of pools themselves, as
35  * well as adding and removing targets to pools.
36  *
37  * Author: Jacques-Charles LAFOUCRIERE <jc.lafoucriere@cea.fr>
38  * Author: Alex Lyashkov <Alexey.Lyashkov@Sun.COM>
39  * Author: Nathaniel Rutman <Nathan.Rutman@Sun.COM>
40  */
41
42 #define DEBUG_SUBSYSTEM S_CLASS
43
44 #include <obd_target.h>
45 #include <obd_support.h>
46 #include <lu_object.h>
47
48 /**
49  * Initialize the pool data structures at startup.
50  *
51  * Allocate and initialize the pool data structures with the specified
52  * array size.  If pool count is not specified (\a count == 0), then
53  * POOL_INIT_COUNT will be used.  Allocating a non-zero initial array
54  * size avoids the need to reallocate as new pools are added.
55  *
56  * \param[in] op        pool structure
57  * \param[in] count     initial size of the target op_array[] array
58  *
59  * \retval              0 indicates successful pool initialization
60  * \retval              negative error number on failure
61  */
62 #define POOL_INIT_COUNT 2
63 int lu_tgt_pool_init(struct lu_tgt_pool *op, unsigned int count)
64 {
65         ENTRY;
66
67         if (count == 0)
68                 count = POOL_INIT_COUNT;
69         op->op_array = NULL;
70         op->op_count = 0;
71         init_rwsem(&op->op_rw_sem);
72         op->op_size = count * sizeof(op->op_array[0]);
73         OBD_ALLOC(op->op_array, op->op_size);
74         if (op->op_array == NULL) {
75                 op->op_size = 0;
76                 RETURN(-ENOMEM);
77         }
78         EXIT;
79         return 0;
80 }
81 EXPORT_SYMBOL(lu_tgt_pool_init);
82
83 /**
84  * Increase the op_array size to hold more targets in this pool.
85  *
86  * The size is increased to at least \a min_count, but may be larger
87  * for an existing pool since ->op_array[] is growing exponentially.
88  * Caller must hold write op_rwlock.
89  *
90  * \param[in] op        pool structure
91  * \param[in] min_count minimum number of entries to handle
92  *
93  * \retval              0 on success
94  * \retval              negative error number on failure.
95  */
96 int lu_tgt_pool_extend(struct lu_tgt_pool *op, unsigned int min_count)
97 {
98         __u32 *new;
99         __u32 new_size;
100
101         LASSERT(min_count != 0);
102
103         if (op->op_count * sizeof(op->op_array[0]) < op->op_size)
104                 return 0;
105
106         new_size = max_t(__u32, min_count * sizeof(op->op_array[0]),
107                          2 * op->op_size);
108         OBD_ALLOC(new, new_size);
109         if (new == NULL)
110                 return -ENOMEM;
111
112         /* copy old array to new one */
113         memcpy(new, op->op_array, op->op_size);
114         OBD_FREE(op->op_array, op->op_size);
115         op->op_array = new;
116         op->op_size = new_size;
117
118         return 0;
119 }
120 EXPORT_SYMBOL(lu_tgt_pool_extend);
121
122 /**
123  * Add a new target to an existing pool.
124  *
125  * Add a new target device to the pool previously created and returned by
126  * lod_pool_new().  Each target can only be in each pool at most one time.
127  *
128  * \param[in] op        target pool to add new entry
129  * \param[in] idx       pool index number to add to the \a op array
130  * \param[in] min_count minimum number of entries to expect in the pool
131  *
132  * \retval              0 if target could be added to the pool
133  * \retval              negative error if target \a idx was not added
134  */
135 int lu_tgt_pool_add_lock(struct lu_tgt_pool *op, __u32 idx,
136                          unsigned int min_count, bool lock)
137 {
138         unsigned int i;
139         int rc = 0;
140         ENTRY;
141
142         if (lock)
143                 down_write(&op->op_rw_sem);
144
145         /* search ost in pool array */
146         for (i = 0; i < op->op_count; i++) {
147                 if (op->op_array[i] == idx)
148                         GOTO(out, rc = -EEXIST);
149         }
150
151         rc = lu_tgt_pool_extend(op, min_count);
152         if (rc)
153                 GOTO(out, rc);
154
155         /* ost not found we add it */
156         op->op_array[op->op_count] = idx;
157         op->op_count++;
158         EXIT;
159 out:
160         if (lock)
161                 up_write(&op->op_rw_sem);
162         return rc;
163 }
164 EXPORT_SYMBOL(lu_tgt_pool_add_lock);
165
166 /**
167  * Remove an existing pool from the system.
168  *
169  * The specified pool must have previously been allocated by
170  * lod_pool_new() and not have any target members in the pool.
171  * If the removed target is not the last, compact the array
172  * to remove empty spaces.
173  *
174  * \param[in] op        pointer to the original data structure
175  * \param[in] idx       target index to be removed
176  *
177  * \retval              0 on success
178  * \retval              negative error number on failure
179  */
180 int lu_tgt_pool_remove(struct lu_tgt_pool *op, __u32 idx)
181 {
182         unsigned int i;
183         ENTRY;
184
185         down_write(&op->op_rw_sem);
186
187         for (i = 0; i < op->op_count; i++) {
188                 if (op->op_array[i] == idx) {
189                         memmove(&op->op_array[i], &op->op_array[i + 1],
190                                 (op->op_count - i - 1) *
191                                 sizeof(op->op_array[0]));
192                         op->op_count--;
193                         up_write(&op->op_rw_sem);
194                         EXIT;
195                         return 0;
196                 }
197         }
198
199         up_write(&op->op_rw_sem);
200         RETURN(-EINVAL);
201 }
202 EXPORT_SYMBOL(lu_tgt_pool_remove);
203
204 int lu_tgt_check_index(int idx, struct lu_tgt_pool *osts)
205 {
206         int i, rc = -ENOENT;
207         ENTRY;
208
209         down_read(&osts->op_rw_sem);
210         for (i = 0; i < osts->op_count; i++) {
211                 if (osts->op_array[i] == idx)
212                         GOTO(out, rc = 0);
213         }
214         EXIT;
215 out:
216         up_read(&osts->op_rw_sem);
217         return rc;
218 }
219 EXPORT_SYMBOL(lu_tgt_check_index);
220
221 /**
222  * Free the pool after it was emptied and removed from /proc.
223  *
224  * Note that all of the child/target entries referenced by this pool
225  * must have been removed by lod_ost_pool_remove() before it can be
226  * deleted from memory.
227  *
228  * \param[in] op        pool to be freed.
229  */
230 void lu_tgt_pool_free(struct lu_tgt_pool *op)
231 {
232         ENTRY;
233
234         if (op->op_size == 0)
235                 RETURN_EXIT;
236
237         down_write(&op->op_rw_sem);
238
239         OBD_FREE(op->op_array, op->op_size);
240         op->op_array = NULL;
241         op->op_count = 0;
242         op->op_size = 0;
243
244         up_write(&op->op_rw_sem);
245         EXIT;
246 }
247 EXPORT_SYMBOL(lu_tgt_pool_free);