~ubuntu-branches/ubuntu/trusty/linux-linaro-omap/trusty

« back to all changes in this revision

Viewing changes to ubuntu/iscsitarget/target.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-57i0gl3v99b3lkfg
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>
3
 
 *
4
 
 * Released under the terms of the GNU GPL v2.0.
5
 
 */
6
 
 
7
 
#include "iscsi.h"
8
 
#include "digest.h"
9
 
#include "iscsi_dbg.h"
10
 
 
11
 
#define MAX_NR_TARGETS  (1UL << 30)
12
 
 
13
 
static LIST_HEAD(target_list);
14
 
static DEFINE_SEMAPHORE(target_list_sem);
15
 
static u32 next_target_id;
16
 
static u32 nr_targets;
17
 
 
18
 
static struct iscsi_sess_param default_session_param = {
19
 
        .initial_r2t = 1,
20
 
        .immediate_data = 1,
21
 
        .max_connections = 1,
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,
34
 
        .ofmarker = 0,
35
 
        .ifmarker = 0,
36
 
        .ofmarkint = 2048,
37
 
        .ifmarkint = 2048,
38
 
};
39
 
 
40
 
static struct iscsi_trgt_param default_target_param = {
41
 
        .wthreads = DEFAULT_NR_WTHREADS,
42
 
        .target_type = 0,
43
 
        .queued_cmnds = DEFAULT_NR_QUEUED_CMNDS,
44
 
};
45
 
 
46
 
inline int target_lock(struct iscsi_target *target, int interruptible)
47
 
{
48
 
        int err = 0;
49
 
 
50
 
        if (interruptible)
51
 
                err = down_interruptible(&target->target_sem);
52
 
        else
53
 
                down(&target->target_sem);
54
 
 
55
 
        return err;
56
 
}
57
 
 
58
 
inline void target_unlock(struct iscsi_target *target)
59
 
{
60
 
        up(&target->target_sem);
61
 
}
62
 
 
63
 
static struct iscsi_target *__target_lookup_by_id(u32 id)
64
 
{
65
 
        struct iscsi_target *target;
66
 
 
67
 
        list_for_each_entry(target, &target_list, t_list) {
68
 
                if (target->tid == id)
69
 
                        return target;
70
 
        }
71
 
        return NULL;
72
 
}
73
 
 
74
 
static struct iscsi_target *__target_lookup_by_name(char *name)
75
 
{
76
 
        struct iscsi_target *target;
77
 
 
78
 
        list_for_each_entry(target, &target_list, t_list) {
79
 
                if (!strcmp(target->name, name))
80
 
                        return target;
81
 
        }
82
 
        return NULL;
83
 
}
84
 
 
85
 
struct iscsi_target *target_lookup_by_id(u32 id)
86
 
{
87
 
        struct iscsi_target *target;
88
 
 
89
 
        down(&target_list_sem);
90
 
        target = __target_lookup_by_id(id);
91
 
        up(&target_list_sem);
92
 
 
93
 
        return target;
94
 
}
95
 
 
96
 
static int target_thread_start(struct iscsi_target *target)
97
 
{
98
 
        int err;
99
 
 
100
 
        if ((err = nthread_start(target)) < 0)
101
 
                return err;
102
 
 
103
 
        if (!worker_thread_pool) {
104
 
                err = wthread_start(target->wthread_info,
105
 
                                    target->trgt_param.wthreads, target->tid);
106
 
                if (err)
107
 
                        nthread_stop(target);
108
 
        }
109
 
 
110
 
        return err;
111
 
}
112
 
 
113
 
static void target_thread_stop(struct iscsi_target *target)
114
 
{
115
 
        if (!worker_thread_pool)
116
 
                wthread_stop(target->wthread_info);
117
 
 
118
 
        nthread_stop(target);
119
 
}
120
 
 
121
 
static int iscsi_target_create(struct target_info *info, u32 tid)
122
 
{
123
 
        int err = -EINVAL, len;
124
 
        char *name = info->name;
125
 
        struct iscsi_target *target;
126
 
 
127
 
        dprintk(D_SETUP, "%u %s\n", tid, name);
128
 
 
129
 
        if (!(len = strlen(name))) {
130
 
                eprintk("The length of the target name is zero %u\n", tid);
131
 
                return err;
132
 
        }
133
 
 
134
 
        if (!try_module_get(THIS_MODULE)) {
135
 
                eprintk("Fail to get module %u\n", tid);
136
 
                return err;
137
 
        }
138
 
 
139
 
        target = kzalloc(sizeof(*target), GFP_KERNEL);
140
 
        if (!target) {
141
 
                err = -ENOMEM;
142
 
                goto out;
143
 
        }
144
 
 
145
 
        if (!worker_thread_pool) {
146
 
                target->wthread_info = kmalloc(sizeof(struct worker_thread_info), GFP_KERNEL);
147
 
                if (!target->wthread_info) {
148
 
                        err = -ENOMEM;
149
 
                        goto out;
150
 
                }
151
 
        }
152
 
 
153
 
        target->tid = info->tid = tid;
154
 
 
155
 
        memcpy(&target->sess_param, &default_session_param, sizeof(default_session_param));
156
 
        memcpy(&target->trgt_param, &default_target_param, sizeof(default_target_param));
157
 
 
158
 
        strncpy(target->name, name, sizeof(target->name) - 1);
159
 
 
160
 
        sema_init(&target->target_sem, 1);
161
 
        spin_lock_init(&target->session_list_lock);
162
 
 
163
 
        INIT_LIST_HEAD(&target->session_list);
164
 
        INIT_LIST_HEAD(&target->volumes);
165
 
 
166
 
        atomic_set(&target->nr_volumes, 0);
167
 
 
168
 
        nthread_init(target);
169
 
 
170
 
        if (!worker_thread_pool)
171
 
                wthread_init(target->wthread_info);
172
 
        else
173
 
                target->wthread_info = worker_thread_pool;
174
 
 
175
 
 
176
 
        if ((err = target_thread_start(target)) < 0) {
177
 
                target_thread_stop(target);
178
 
                goto out;
179
 
        }
180
 
 
181
 
        list_add(&target->t_list, &target_list);
182
 
 
183
 
        return 0;
184
 
out:
185
 
        if (!worker_thread_pool)
186
 
                kfree(target->wthread_info);
187
 
        kfree(target);
188
 
        module_put(THIS_MODULE);
189
 
 
190
 
        return err;
191
 
}
192
 
 
193
 
int target_add(struct target_info *info)
194
 
{
195
 
        u32 tid = info->tid;
196
 
        int err;
197
 
 
198
 
        err = down_interruptible(&target_list_sem);
199
 
        if (err < 0)
200
 
                return err;
201
 
 
202
 
        if (nr_targets > MAX_NR_TARGETS) {
203
 
                err = -EBUSY;
204
 
                goto out;
205
 
        }
206
 
 
207
 
        if (__target_lookup_by_name(info->name) || 
208
 
                        (tid && __target_lookup_by_id(tid))) {
209
 
                err = -EEXIST;
210
 
                goto out;
211
 
        }
212
 
 
213
 
        if (!tid) {
214
 
                do {
215
 
                        if (!++next_target_id)
216
 
                                ++next_target_id;
217
 
                } while (__target_lookup_by_id(next_target_id));
218
 
 
219
 
                tid = next_target_id;
220
 
        }
221
 
 
222
 
        err = iscsi_target_create(info, tid);
223
 
        if (!err)
224
 
                nr_targets++;
225
 
out:
226
 
        up(&target_list_sem);
227
 
 
228
 
        return err;
229
 
}
230
 
 
231
 
static void target_destroy(struct iscsi_target *target)
232
 
{
233
 
        dprintk(D_SETUP, "%u\n", target->tid);
234
 
 
235
 
        target_thread_stop(target);
236
 
 
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);
242
 
        }
243
 
 
244
 
        if (!worker_thread_pool)
245
 
                kfree(target->wthread_info);
246
 
        kfree(target);
247
 
 
248
 
        module_put(THIS_MODULE);
249
 
}
250
 
 
251
 
/* @locking: target_list_sem must be locked */
252
 
static int __target_del(struct iscsi_target *target)
253
 
{
254
 
        int err;
255
 
 
256
 
        target_lock(target, 0);
257
 
 
258
 
        if (!list_empty(&target->session_list)) {
259
 
                struct iscsi_session *session;
260
 
 
261
 
                do {
262
 
                        session = list_entry(target->session_list.next,
263
 
                                                struct iscsi_session, list);
264
 
                        err = session_del(target, session->sid);
265
 
                        if (err < 0) {
266
 
                                target_unlock(target);
267
 
                                return err;
268
 
                        }
269
 
                } while (!list_empty(&target->session_list));
270
 
        }
271
 
 
272
 
        list_del(&target->t_list);
273
 
        nr_targets--;
274
 
 
275
 
        target_unlock(target);
276
 
        target_destroy(target);
277
 
 
278
 
        return 0;
279
 
}
280
 
 
281
 
int target_del(u32 id)
282
 
{
283
 
        struct iscsi_target *target;
284
 
        int err;
285
 
 
286
 
        err = down_interruptible(&target_list_sem);
287
 
        if (err < 0)
288
 
                return err;
289
 
 
290
 
        target = __target_lookup_by_id(id);
291
 
        if (!target) {
292
 
                err = -ENOENT;
293
 
                goto out;
294
 
        }
295
 
 
296
 
        err = __target_del(target);
297
 
out:
298
 
        up(&target_list_sem);
299
 
 
300
 
        return err;
301
 
}
302
 
 
303
 
void target_del_all(void)
304
 
{
305
 
        struct iscsi_target *target, *tmp;
306
 
        int err;
307
 
 
308
 
        down(&target_list_sem);
309
 
 
310
 
        if (!list_empty(&target_list))
311
 
                iprintk("Removing all connections, sessions and targets\n");
312
 
 
313
 
        list_for_each_entry_safe(target, tmp, &target_list, t_list) {
314
 
                u32 tid = target->tid;
315
 
                err =__target_del(target);
316
 
                if (err)
317
 
                        eprintk("Error deleteing target %u: %d\n", tid, err);
318
 
        }
319
 
 
320
 
        next_target_id = 0;
321
 
 
322
 
        up(&target_list_sem);
323
 
}
324
 
 
325
 
static void *iet_seq_start(struct seq_file *m, loff_t *pos)
326
 
{
327
 
        int err;
328
 
 
329
 
        /* are you sure this is to be interruptible? */
330
 
        err = down_interruptible(&target_list_sem);
331
 
        if (err < 0)
332
 
                return ERR_PTR(err);
333
 
 
334
 
        return seq_list_start(&target_list, *pos);
335
 
}
336
 
 
337
 
static void *iet_seq_next(struct seq_file *m, void *v, loff_t *pos)
338
 
{
339
 
        return seq_list_next(v, &target_list, pos);
340
 
}
341
 
 
342
 
static void iet_seq_stop(struct seq_file *m, void *v)
343
 
{
344
 
        up(&target_list_sem);
345
 
}
346
 
 
347
 
static int iet_seq_show(struct seq_file *m, void *p)
348
 
{
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);
352
 
        int err;
353
 
 
354
 
        /* relly, interruptible?  I'd think target_lock(target, 0)
355
 
         * would be more appropriate. --lge */
356
 
        err = target_lock(target, 1);
357
 
        if (err < 0)
358
 
                return err;
359
 
 
360
 
        seq_printf(m, "tid:%u name:%s\n", target->tid, target->name);
361
 
 
362
 
        func(m, target);
363
 
 
364
 
        target_unlock(target);
365
 
 
366
 
        return 0;
367
 
}
368
 
 
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,
374
 
};