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_lock(struct lu_tgt_pool *op, __u32 idx,
136 unsigned int min_count, bool lock)
143 down_write(&op->op_rw_sem);
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);
151 rc = lu_tgt_pool_extend(op, min_count);
155 /* ost not found we add it */
156 op->op_array[op->op_count] = idx;
161 up_write(&op->op_rw_sem);
164 EXPORT_SYMBOL(lu_tgt_pool_add_lock);
167 * Remove an existing pool from the system.
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.
174 * \param[in] op pointer to the original data structure
175 * \param[in] idx target index to be removed
177 * \retval 0 on success
178 * \retval negative error number on failure
180 int lu_tgt_pool_remove(struct lu_tgt_pool *op, __u32 idx)
185 down_write(&op->op_rw_sem);
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]));
193 up_write(&op->op_rw_sem);
199 up_write(&op->op_rw_sem);
202 EXPORT_SYMBOL(lu_tgt_pool_remove);
204 int lu_tgt_check_index(int idx, struct lu_tgt_pool *osts)
209 down_read(&osts->op_rw_sem);
210 for (i = 0; i < osts->op_count; i++) {
211 if (osts->op_array[i] == idx)
216 up_read(&osts->op_rw_sem);
219 EXPORT_SYMBOL(lu_tgt_check_index);
222 * Free the pool after it was emptied and removed from /proc.
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.
228 * \param[in] op pool to be freed.
230 void lu_tgt_pool_free(struct lu_tgt_pool *op)
234 if (op->op_size == 0)
237 down_write(&op->op_rw_sem);
239 OBD_FREE(op->op_array, op->op_size);
244 up_write(&op->op_rw_sem);
247 EXPORT_SYMBOL(lu_tgt_pool_free);