4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
24 * Use is subject to license terms.
26 * Copyright (c) 2012, 2017, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
32 * lustre/target/tgt_pool.c
34 * This file handles creation, lookup, and removal of pools themselves, as
35 * well as adding and removing targets to pools.
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>
42 #define DEBUG_SUBSYSTEM S_CLASS
44 #include <obd_target.h>
45 #include <obd_support.h>
48 * Initialize the pool data structures at startup.
50 * Allocate and initialize the pool data structures with the specified
51 * array size. If pool count is not specified (\a count == 0), then
52 * POOL_INIT_COUNT will be used. Allocating a non-zero initial array
53 * size avoids the need to reallocate as new pools are added.
55 * \param[in] op pool structure
56 * \param[in] count initial size of the target op_array[] array
58 * \retval 0 indicates successful pool initialization
59 * \retval negative error number on failure
61 #define POOL_INIT_COUNT 2
62 int tgt_pool_init(struct lu_tgt_pool *op, unsigned int count)
67 count = POOL_INIT_COUNT;
70 init_rwsem(&op->op_rw_sem);
71 op->op_size = count * sizeof(op->op_array[0]);
72 OBD_ALLOC(op->op_array, op->op_size);
73 if (op->op_array == NULL) {
80 EXPORT_SYMBOL(tgt_pool_init);
83 * Increase the op_array size to hold more targets in this pool.
85 * The size is increased to at least \a min_count, but may be larger
86 * for an existing pool since ->op_array[] is growing exponentially.
87 * Caller must hold write op_rwlock.
89 * \param[in] op pool structure
90 * \param[in] min_count minimum number of entries to handle
92 * \retval 0 on success
93 * \retval negative error number on failure.
95 int tgt_pool_extend(struct lu_tgt_pool *op, unsigned int min_count)
100 LASSERT(min_count != 0);
102 if (op->op_count * sizeof(op->op_array[0]) < op->op_size)
105 new_size = max_t(__u32, min_count * sizeof(op->op_array[0]),
107 OBD_ALLOC(new, new_size);
111 /* copy old array to new one */
112 memcpy(new, op->op_array, op->op_size);
113 OBD_FREE(op->op_array, op->op_size);
115 op->op_size = new_size;
119 EXPORT_SYMBOL(tgt_pool_extend);
122 * Add a new target to an existing pool.
124 * Add a new target device to the pool previously created and returned by
125 * lod_pool_new(). Each target can only be in each pool at most one time.
127 * \param[in] op target pool to add new entry
128 * \param[in] idx pool index number to add to the \a op array
129 * \param[in] min_count minimum number of entries to expect in the pool
131 * \retval 0 if target could be added to the pool
132 * \retval negative error if target \a idx was not added
134 int tgt_pool_add(struct lu_tgt_pool *op, __u32 idx, unsigned int min_count)
140 down_write(&op->op_rw_sem);
142 rc = tgt_pool_extend(op, min_count);
146 /* search ost in pool array */
147 for (i = 0; i < op->op_count; i++) {
148 if (op->op_array[i] == idx)
149 GOTO(out, rc = -EEXIST);
151 /* ost not found we add it */
152 op->op_array[op->op_count] = idx;
156 up_write(&op->op_rw_sem);
159 EXPORT_SYMBOL(tgt_pool_add);
162 * Remove an existing pool from the system.
164 * The specified pool must have previously been allocated by
165 * lod_pool_new() and not have any target members in the pool.
166 * If the removed target is not the last, compact the array
167 * to remove empty spaces.
169 * \param[in] op pointer to the original data structure
170 * \param[in] idx target index to be removed
172 * \retval 0 on success
173 * \retval negative error number on failure
175 int tgt_pool_remove(struct lu_tgt_pool *op, __u32 idx)
180 down_write(&op->op_rw_sem);
182 for (i = 0; i < op->op_count; i++) {
183 if (op->op_array[i] == idx) {
184 memmove(&op->op_array[i], &op->op_array[i + 1],
185 (op->op_count - i - 1) *
186 sizeof(op->op_array[0]));
188 up_write(&op->op_rw_sem);
194 up_write(&op->op_rw_sem);
197 EXPORT_SYMBOL(tgt_pool_remove);
199 int tgt_check_index(int idx, struct lu_tgt_pool *osts)
204 down_read(&osts->op_rw_sem);
205 for (i = 0; i < osts->op_count; i++) {
206 if (osts->op_array[i] == idx)
212 up_read(&osts->op_rw_sem);
215 EXPORT_SYMBOL(tgt_check_index);
218 * Free the pool after it was emptied and removed from /proc.
220 * Note that all of the child/target entries referenced by this pool
221 * must have been removed by lod_ost_pool_remove() before it can be
222 * deleted from memory.
224 * \param[in] op pool to be freed.
226 * \retval 0 on success or if pool was already freed
228 int tgt_pool_free(struct lu_tgt_pool *op)
232 if (op->op_size == 0)
235 down_write(&op->op_rw_sem);
237 OBD_FREE(op->op_array, op->op_size);
242 up_write(&op->op_rw_sem);
245 EXPORT_SYMBOL(tgt_pool_free);