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>
46 #include <lu_object.h>
49 * Initialize the pool data structures at startup.
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.
56 * \param[in] op pool structure
57 * \param[in] count initial size of the target op_array[] array
59 * \retval 0 indicates successful pool initialization
60 * \retval negative error number on failure
62 #define POOL_INIT_COUNT 2
63 int lu_tgt_pool_init(struct lu_tgt_pool *op, unsigned int count)
68 count = POOL_INIT_COUNT;
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) {
81 EXPORT_SYMBOL(lu_tgt_pool_init);
84 * Increase the op_array size to hold more targets in this pool.
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.
90 * \param[in] op pool structure
91 * \param[in] min_count minimum number of entries to handle
93 * \retval 0 on success
94 * \retval negative error number on failure.
96 int lu_tgt_pool_extend(struct lu_tgt_pool *op, unsigned int min_count)
101 LASSERT(min_count != 0);
103 if (op->op_count * sizeof(op->op_array[0]) < op->op_size)
106 new_size = max_t(__u32, min_count * sizeof(op->op_array[0]),
108 OBD_ALLOC(new, new_size);
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);
116 op->op_size = new_size;
120 EXPORT_SYMBOL(lu_tgt_pool_extend);
123 * Add a new target to an existing pool.
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.
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
132 * \retval 0 if target could be added to the pool
133 * \retval negative error if target \a idx was not added
135 int lu_tgt_pool_add(struct lu_tgt_pool *op, __u32 idx, unsigned int min_count)
141 down_write(&op->op_rw_sem);
143 /* search ost in pool array */
144 for (i = 0; i < op->op_count; i++) {
145 if (op->op_array[i] == idx)
146 GOTO(out, rc = -EEXIST);
149 rc = lu_tgt_pool_extend(op, min_count);
153 /* ost not found we add it */
154 op->op_array[op->op_count] = idx;
158 up_write(&op->op_rw_sem);
161 EXPORT_SYMBOL(lu_tgt_pool_add);
164 * Remove an existing pool from the system.
166 * The specified pool must have previously been allocated by
167 * lod_pool_new() and not have any target members in the pool.
168 * If the removed target is not the last, compact the array
169 * to remove empty spaces.
171 * \param[in] op pointer to the original data structure
172 * \param[in] idx target index to be removed
174 * \retval 0 on success
175 * \retval negative error number on failure
177 int lu_tgt_pool_remove(struct lu_tgt_pool *op, __u32 idx)
182 down_write(&op->op_rw_sem);
184 for (i = 0; i < op->op_count; i++) {
185 if (op->op_array[i] == idx) {
186 memmove(&op->op_array[i], &op->op_array[i + 1],
187 (op->op_count - i - 1) *
188 sizeof(op->op_array[0]));
190 up_write(&op->op_rw_sem);
196 up_write(&op->op_rw_sem);
199 EXPORT_SYMBOL(lu_tgt_pool_remove);
201 int lu_tgt_check_index(int idx, struct lu_tgt_pool *osts)
206 down_read(&osts->op_rw_sem);
207 for (i = 0; i < osts->op_count; i++) {
208 if (osts->op_array[i] == idx)
213 up_read(&osts->op_rw_sem);
216 EXPORT_SYMBOL(lu_tgt_check_index);
219 * Free the pool after it was emptied and removed from /proc.
221 * Note that all of the child/target entries referenced by this pool
222 * must have been removed by lod_ost_pool_remove() before it can be
223 * deleted from memory.
225 * \param[in] op pool to be freed.
227 void lu_tgt_pool_free(struct lu_tgt_pool *op)
231 if (op->op_size == 0)
234 down_write(&op->op_rw_sem);
236 OBD_FREE(op->op_array, op->op_size);
241 up_write(&op->op_rw_sem);
244 EXPORT_SYMBOL(lu_tgt_pool_free);