3
* (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
4
* This code is licenced under the GPL.
7
#include <linux/types.h>
8
#include <linux/parser.h>
11
#include "iscsi_dbg.h"
14
struct iet_volume *volume_lookup(struct iscsi_target *target, u32 lun)
16
struct iet_volume *volume;
18
list_for_each_entry(volume, &target->volumes, list) {
19
if (volume->lun == lun)
31
static match_table_t tokens = {
32
{Opt_type, "Type=%s"},
33
{Opt_iomode, "IOMode=%s"},
37
static int set_iotype(struct iet_volume *volume, char *params)
40
substring_t args[MAX_OPT_ARGS];
41
char *p, *argp = NULL, *buf = (char *) get_zeroed_page(GFP_USER);
45
strncpy(buf, params, PAGE_CACHE_SIZE);
47
while ((p = strsep(&buf, ",")) != NULL) {
52
token = match_token(p, tokens, args);
55
if (!(argp = match_strdup(&args[0])))
57
if (argp && !(volume->iotype = get_iotype(argp)))
62
if (!(argp = match_strdup(&args[0])))
64
if (argp && !strcmp(argp, "ro"))
65
SetLUReadonly(volume);
66
else if (argp && !strcmp(argp, "wb"))
75
if (!err && !volume->iotype && !(volume->iotype = get_iotype("fileio"))) {
76
eprintk("%s\n", "Cannot find fileio");
80
free_page((unsigned long) buf);
85
int volume_add(struct iscsi_target *target, struct volume_info *info)
88
struct iet_volume *volume;
91
volume = volume_lookup(target, info->lun);
95
if (info->lun > 0x3fff)
98
volume = kzalloc(sizeof(*volume), GFP_KERNEL);
102
volume->target = target;
103
volume->lun = info->lun;
105
args = kzalloc(info->args_len + 1, GFP_KERNEL);
111
ret = copy_from_user(args, (void *)(unsigned long)info->args_ptr,
118
ret = set_iotype(volume, args);
122
ret = volume->iotype->attach(volume, args);
126
INIT_LIST_HEAD(&volume->queue.wait_list);
127
spin_lock_init(&volume->queue.queue_lock);
128
spin_lock_init(&volume->reserve_lock);
130
volume->l_state = IDEV_RUNNING;
131
atomic_set(&volume->l_count, 0);
133
list_add_tail(&volume->list, &target->volumes);
134
atomic_inc(&target->nr_volumes);
142
put_iotype(volume->iotype);
148
void iscsi_volume_destroy(struct iet_volume *volume)
150
assert(volume->l_state == IDEV_DEL);
151
assert(!atomic_read(&volume->l_count));
153
volume->iotype->detach(volume);
154
put_iotype(volume->iotype);
155
list_del(&volume->list);
159
int iscsi_volume_del(struct iscsi_target *target, struct volume_info *info)
161
struct iet_volume *volume;
163
eprintk("%x %x\n", target->tid, info->lun);
164
if (!(volume = volume_lookup(target, info->lun)))
167
volume->l_state = IDEV_DEL;
168
atomic_dec(&target->nr_volumes);
169
if (!atomic_read(&volume->l_count))
170
iscsi_volume_destroy(volume);
175
struct iet_volume *volume_get(struct iscsi_target *target, u32 lun)
177
struct iet_volume *volume;
179
if ((volume = volume_lookup(target, lun))) {
180
if (volume->l_state == IDEV_RUNNING)
181
atomic_inc(&volume->l_count);
188
void volume_put(struct iet_volume *volume)
190
if (atomic_dec_and_test(&volume->l_count) && volume->l_state == IDEV_DEL)
191
iscsi_volume_destroy(volume);
194
int volume_reserve(struct iet_volume *volume, u64 sid)
199
spin_lock(&volume->reserve_lock);
200
if (volume->reserve_sid && volume->reserve_sid != sid) {
201
spin_unlock(&volume->reserve_lock);
205
volume->reserve_sid = sid;
206
spin_unlock(&volume->reserve_lock);
211
int is_volume_reserved(struct iet_volume *volume, u64 sid)
213
if (!volume || !volume->reserve_sid || volume->reserve_sid == sid)
219
int volume_release(struct iet_volume *volume, u64 sid, int force)
221
if (force || volume->reserve_sid == sid)
222
volume->reserve_sid = 0;
227
static void iet_volume_info_show(struct seq_file *seq, struct iscsi_target *target)
229
struct iet_volume *volume;
231
list_for_each_entry(volume, &target->volumes, list) {
232
seq_printf(seq, "\tlun:%u state:%x iotype:%s",
233
volume->lun, volume->l_state, volume->iotype->name);
234
if (LUReadonly(volume))
235
seq_printf(seq, " iomode:ro");
236
else if (LUWCache(volume))
237
seq_printf(seq, " iomode:wb");
239
seq_printf(seq, " iomode:wt");
241
if (volume->iotype->show)
242
volume->iotype->show(volume, seq);
244
seq_printf(seq, "\n");
248
static int iet_volume_seq_open(struct inode *inode, struct file *file)
251
res = seq_open(file, &iet_seq_op);
253
((struct seq_file *)file->private_data)->private =
254
iet_volume_info_show;
258
struct file_operations volume_seq_fops = {
259
.owner = THIS_MODULE,
260
.open = iet_volume_seq_open,
263
.release = seq_release,