2
* Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>
4
* Released under the terms of the GNU GPL v2.0.
11
#define MAX_NR_TARGETS (1UL << 30)
13
static LIST_HEAD(target_list);
14
static DEFINE_SEMAPHORE(target_list_sem);
15
static u32 next_target_id;
16
static u32 nr_targets;
18
static struct iscsi_sess_param default_session_param = {
22
.max_recv_data_length = 8192,
23
.max_xmit_data_length = 8192,
24
.max_burst_length = 262144,
25
.first_burst_length = 65536,
26
.default_wait_time = 2,
27
.default_retain_time = 20,
28
.max_outstanding_r2t = 1,
29
.data_pdu_inorder = 1,
30
.data_sequence_inorder = 1,
31
.error_recovery_level = 0,
32
.header_digest = DIGEST_NONE,
33
.data_digest = DIGEST_NONE,
40
static struct iscsi_trgt_param default_target_param = {
41
.wthreads = DEFAULT_NR_WTHREADS,
43
.queued_cmnds = DEFAULT_NR_QUEUED_CMNDS,
46
inline int target_lock(struct iscsi_target *target, int interruptible)
51
err = down_interruptible(&target->target_sem);
53
down(&target->target_sem);
58
inline void target_unlock(struct iscsi_target *target)
60
up(&target->target_sem);
63
static struct iscsi_target *__target_lookup_by_id(u32 id)
65
struct iscsi_target *target;
67
list_for_each_entry(target, &target_list, t_list) {
68
if (target->tid == id)
74
static struct iscsi_target *__target_lookup_by_name(char *name)
76
struct iscsi_target *target;
78
list_for_each_entry(target, &target_list, t_list) {
79
if (!strcmp(target->name, name))
85
struct iscsi_target *target_lookup_by_id(u32 id)
87
struct iscsi_target *target;
89
down(&target_list_sem);
90
target = __target_lookup_by_id(id);
96
static int target_thread_start(struct iscsi_target *target)
100
if ((err = nthread_start(target)) < 0)
103
if (!worker_thread_pool) {
104
err = wthread_start(target->wthread_info,
105
target->trgt_param.wthreads, target->tid);
107
nthread_stop(target);
113
static void target_thread_stop(struct iscsi_target *target)
115
if (!worker_thread_pool)
116
wthread_stop(target->wthread_info);
118
nthread_stop(target);
121
static int iscsi_target_create(struct target_info *info, u32 tid)
123
int err = -EINVAL, len;
124
char *name = info->name;
125
struct iscsi_target *target;
127
dprintk(D_SETUP, "%u %s\n", tid, name);
129
if (!(len = strlen(name))) {
130
eprintk("The length of the target name is zero %u\n", tid);
134
if (!try_module_get(THIS_MODULE)) {
135
eprintk("Fail to get module %u\n", tid);
139
target = kzalloc(sizeof(*target), GFP_KERNEL);
145
if (!worker_thread_pool) {
146
target->wthread_info = kmalloc(sizeof(struct worker_thread_info), GFP_KERNEL);
147
if (!target->wthread_info) {
153
target->tid = info->tid = tid;
155
memcpy(&target->sess_param, &default_session_param, sizeof(default_session_param));
156
memcpy(&target->trgt_param, &default_target_param, sizeof(default_target_param));
158
strncpy(target->name, name, sizeof(target->name) - 1);
160
sema_init(&target->target_sem, 1);
161
spin_lock_init(&target->session_list_lock);
163
INIT_LIST_HEAD(&target->session_list);
164
INIT_LIST_HEAD(&target->volumes);
166
atomic_set(&target->nr_volumes, 0);
168
nthread_init(target);
170
if (!worker_thread_pool)
171
wthread_init(target->wthread_info);
173
target->wthread_info = worker_thread_pool;
176
if ((err = target_thread_start(target)) < 0) {
177
target_thread_stop(target);
181
list_add(&target->t_list, &target_list);
185
if (!worker_thread_pool)
186
kfree(target->wthread_info);
188
module_put(THIS_MODULE);
193
int target_add(struct target_info *info)
198
err = down_interruptible(&target_list_sem);
202
if (nr_targets > MAX_NR_TARGETS) {
207
if (__target_lookup_by_name(info->name) ||
208
(tid && __target_lookup_by_id(tid))) {
215
if (!++next_target_id)
217
} while (__target_lookup_by_id(next_target_id));
219
tid = next_target_id;
222
err = iscsi_target_create(info, tid);
226
up(&target_list_sem);
231
static void target_destroy(struct iscsi_target *target)
233
dprintk(D_SETUP, "%u\n", target->tid);
235
target_thread_stop(target);
237
while (!list_empty(&target->volumes)) {
238
struct iet_volume *volume;
239
volume = list_entry(target->volumes.next, struct iet_volume, list);
240
volume->l_state = IDEV_DEL;
241
iscsi_volume_destroy(volume);
244
if (!worker_thread_pool)
245
kfree(target->wthread_info);
248
module_put(THIS_MODULE);
251
/* @locking: target_list_sem must be locked */
252
static int __target_del(struct iscsi_target *target)
256
target_lock(target, 0);
258
if (!list_empty(&target->session_list)) {
259
struct iscsi_session *session;
262
session = list_entry(target->session_list.next,
263
struct iscsi_session, list);
264
err = session_del(target, session->sid);
266
target_unlock(target);
269
} while (!list_empty(&target->session_list));
272
list_del(&target->t_list);
275
target_unlock(target);
276
target_destroy(target);
281
int target_del(u32 id)
283
struct iscsi_target *target;
286
err = down_interruptible(&target_list_sem);
290
target = __target_lookup_by_id(id);
296
err = __target_del(target);
298
up(&target_list_sem);
303
void target_del_all(void)
305
struct iscsi_target *target, *tmp;
308
down(&target_list_sem);
310
if (!list_empty(&target_list))
311
iprintk("Removing all connections, sessions and targets\n");
313
list_for_each_entry_safe(target, tmp, &target_list, t_list) {
314
u32 tid = target->tid;
315
err =__target_del(target);
317
eprintk("Error deleteing target %u: %d\n", tid, err);
322
up(&target_list_sem);
325
static void *iet_seq_start(struct seq_file *m, loff_t *pos)
329
/* are you sure this is to be interruptible? */
330
err = down_interruptible(&target_list_sem);
334
return seq_list_start(&target_list, *pos);
337
static void *iet_seq_next(struct seq_file *m, void *v, loff_t *pos)
339
return seq_list_next(v, &target_list, pos);
342
static void iet_seq_stop(struct seq_file *m, void *v)
344
up(&target_list_sem);
347
static int iet_seq_show(struct seq_file *m, void *p)
349
iet_show_info_t *func = (iet_show_info_t *)m->private;
350
struct iscsi_target *target =
351
list_entry(p, struct iscsi_target, t_list);
354
/* relly, interruptible? I'd think target_lock(target, 0)
355
* would be more appropriate. --lge */
356
err = target_lock(target, 1);
360
seq_printf(m, "tid:%u name:%s\n", target->tid, target->name);
364
target_unlock(target);
369
struct seq_operations iet_seq_op = {
370
.start = iet_seq_start,
371
.next = iet_seq_next,
372
.stop = iet_seq_stop,
373
.show = iet_seq_show,