File iscsitarget-svn-174.diff of Package iscsitarget
Index: kernel/wthread.c
===================================================================
--- kernel/wthread.c (revision 138)
+++ kernel/wthread.c (working copy)
@@ -120,7 +120,9 @@
int err;
assert(wt->w_task);
- if ((err = kthread_stop(wt->w_task)) < 0)
+ err = kthread_stop(wt->w_task);
+
+ if (err < 0 && err != -EINTR)
return err;
list_del(&wt->w_list);
Index: kernel/block-io.c
===================================================================
--- kernel/block-io.c (revision 138)
+++ kernel/block-io.c (working copy)
@@ -9,8 +9,9 @@
* This code is licenced under the GPL.
*/
+#include <linux/types.h>
+#include <linux/blkdev.h>
#include <linux/parser.h>
-#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include "iscsi.h"
@@ -28,15 +29,10 @@
struct completion tio_complete;
};
-static int
-blockio_bio_endio(struct bio *bio, unsigned int bytes_done, int error)
+static void blockio_bio_endio(struct bio *bio, int error)
{
struct tio_work *tio_work = bio->bi_private;
- /* Ignore partials */
- if (bio->bi_size)
- return 1;
-
error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO;
if (error)
@@ -47,8 +43,6 @@
complete(&tio_work->tio_complete);
bio_put(bio);
-
- return 0;
}
/*
@@ -254,8 +248,9 @@
};
static int
-parse_blockio_params (struct iet_volume *volume, char *params)
+parse_blockio_params(struct iet_volume *volume, char *params)
{
+ struct blockio_data *info = volume->private;
int err = 0;
char *p, *q;
@@ -290,6 +285,13 @@
goto out;
break;
case Opt_path:
+ if (info->path) {
+ iprintk("Target %s, LUN %u: "
+ "duplicate \"Path\" param\n",
+ volume->target->name, volume->lun);
+ err = -EINVAL;
+ goto out;
+ }
if (!(q = match_strdup(&args[0]))) {
err = -ENOMEM;
goto out;
@@ -302,12 +304,17 @@
case Opt_ignore:
break;
default:
- eprintk("Bad option %s for Lun %u on Target %s \n",
- p, volume->lun, volume->target->name);
+ iprintk("Target %s, LUN %u: unknown param %s\n",
+ volume->target->name, volume->lun, p);
return -EINVAL;
}
}
+ if (!info->path) {
+ iprintk("Target %s, LUN %u: missing \"Path\" param\n",
+ volume->target->name, volume->lun);
+ err = -EINVAL;
+ }
out:
return err;
}
@@ -319,12 +326,13 @@
if (bio_data->bdev)
close_bdev_excl(bio_data->bdev);
+ kfree(bio_data->path);
kfree(volume->private);
}
static int
-blockio_attach (struct iet_volume *volume, char *args)
+blockio_attach(struct iet_volume *volume, char *args)
{
struct blockio_data *bio_data;
int err = 0;
@@ -350,6 +358,10 @@
/* Assign a vendor id, generate scsi id if none exists */
gen_scsiid(volume, bio_data->bdev->bd_inode);
+ /* Offer neither write nor read caching */
+ ClearLURCache(volume);
+ ClearLUWCache(volume);
+
volume->blk_shift = SECTOR_SIZE_BITS;
volume->blk_cnt = bio_data->bdev->bd_inode->i_size >> volume->blk_shift;
Index: kernel/target_disk.c
===================================================================
--- kernel/target_disk.c (revision 138)
+++ kernel/target_disk.c (working copy)
@@ -22,15 +22,18 @@
return sizeof(disconnect_pg);
}
-static int insert_caching_pg(u8 *ptr, int async)
+static int insert_caching_pg(u8 *ptr, int wcache, int rcache)
{
unsigned char caching_pg[] = {0x08, 0x12, 0x10, 0x00, 0xff, 0xff, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
memcpy(ptr, caching_pg, sizeof(caching_pg));
- if (async)
+ if (wcache)
ptr[2] |= 0x04; /* set WCE bit if we're caching writes */
+ if (!rcache)
+ ptr[2] |= 0x01; /* Read Cache Disable */
+
return sizeof(caching_pg);
}
@@ -66,13 +69,15 @@
unsigned char geo_m_pg[] = {0x04, 0x16, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00};
- u32 ncyl, *p;
+ u32 ncyl;
+ u32 n;
/* assume 0xff heads, 15krpm. */
memcpy(ptr, geo_m_pg, sizeof(geo_m_pg));
ncyl = sec >> 14; /* 256 * 64 */
- p = (u32 *)(ptr + 1);
- *p = *p | cpu_to_be32(ncyl);
+ memcpy(&n, ptr+1, sizeof(u32));
+ n = n | cpu_to_be32(ncyl);
+ memcpy(ptr+1, &n, sizeof(u32));
return sizeof(geo_m_pg);
}
@@ -84,6 +89,10 @@
int len = 4, err = 0;
u8 pcode;
+ /* changeable parameter mode pages are unsupported */
+ if ((scb[2] & 0xc0) >> 6 == 0x1)
+ return -1;
+
pcode = req->scb[2] & 0x3f;
assert(!tio);
@@ -118,7 +127,8 @@
len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt);
break;
case 0x8:
- len += insert_caching_pg(data + len, LUAsync(cmnd->lun));
+ len += insert_caching_pg(data + len, LUWCache(cmnd->lun),
+ LURCache(cmnd->lun));
break;
case 0xa:
len += insert_ctrl_m_pg(data + len);
@@ -130,7 +140,8 @@
len += insert_disconnect_pg(data + len);
len += insert_format_m_pg(data + len);
len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt);
- len += insert_caching_pg(data + len, LUAsync(cmnd->lun));
+ len += insert_caching_pg(data + len, LUWCache(cmnd->lun),
+ LURCache(cmnd->lun));
len += insert_ctrl_m_pg(data + len);
len += insert_iec_m_pg(data + len);
break;
@@ -153,7 +164,11 @@
u8 *scb = req->scb;
int err = -1;
- if (((req->scb[1] & 0x3) == 0x3) || (!(req->scb[1] & 0x3) && req->scb[2]))
+ /*
+ * - CmdDt and EVPD both set or EVPD and Page Code set: illegal
+ * - CmdDt set: not supported
+ */
+ if ((scb[1] & 0x3) > 0x1 || (!(scb[1] & 0x3) && scb[2]))
return err;
assert(!tio);
@@ -182,13 +197,6 @@
data[63] = 0x00;
tio_set(tio, 64, 0);
err = 0;
- } else if (scb[1] & 0x2) {
- /* CmdDt bit is set */
- /* We do not support it now. */
- data[1] = 0x1;
- data[5] = 0;
- tio_set(tio, 6, 0);
- err = 0;
} else if (scb[1] & 0x1) {
/* EVPD bit set */
if (scb[2] == 0x0) {
@@ -249,7 +257,8 @@
struct iet_volume *lun;
int rest, idx = 0;
- size = be32_to_cpu(*(u32 *)&req->scb[6]);
+ size = (u32)req->scb[6] << 24 | (u32)req->scb[7] << 16 |
+ (u32)req->scb[8] << 8 | (u32)req->scb[9];
if (size < 16)
return -1;
@@ -363,7 +372,7 @@
list_del_init(&cmnd->list);
err = tio_write(cmnd->lun, tio);
- if (!err && !LUAsync(cmnd->lun))
+ if (!err && !LUWCache(cmnd->lun))
err = tio_sync(cmnd->lun, tio);
return err;
Index: kernel/config.c
===================================================================
--- kernel/config.c (revision 138)
+++ kernel/config.c (working copy)
@@ -40,7 +40,7 @@
int i;
struct proc_dir_entry *ent;
- if (!(proc_iet_dir = proc_mkdir("net/iet", 0)))
+ if (!(proc_iet_dir = proc_mkdir("iet", init_net.proc_net)))
goto err;
proc_iet_dir->owner = THIS_MODULE;
Index: kernel/volume.c
===================================================================
--- kernel/volume.c (revision 138)
+++ kernel/volume.c (working copy)
@@ -4,12 +4,13 @@
* This code is licenced under the GPL.
*/
+#include <linux/types.h>
+#include <linux/parser.h>
+
#include "iscsi.h"
#include "iscsi_dbg.h"
#include "iotype.h"
-#include <linux/parser.h>
-
struct iet_volume *volume_lookup(struct iscsi_target *target, u32 lun)
{
struct iet_volume *volume;
@@ -63,7 +64,7 @@
if (argp && !strcmp(argp, "ro"))
SetLUReadonly(volume);
else if (argp && !strcmp(argp, "wb"))
- SetLUAsync(volume);
+ SetLUWCache(volume);
kfree(argp);
break;
default:
@@ -132,6 +133,8 @@
list_add_tail(&volume->list, &target->volumes);
atomic_inc(&target->nr_volumes);
+ kfree(args);
+
return 0;
free_args:
kfree(args);
@@ -230,10 +233,11 @@
volume->lun, volume->l_state, volume->iotype->name);
if (LUReadonly(volume))
seq_printf(seq, " iomode:ro");
- else if (LUAsync(volume))
+ else if (LUWCache(volume))
seq_printf(seq, " iomode:wb");
else
seq_printf(seq, " iomode:wt");
+
if (volume->iotype->show)
volume->iotype->show(volume, seq);
else
Index: kernel/iscsi.c
===================================================================
--- kernel/iscsi.c (revision 138)
+++ kernel/iscsi.c (working copy)
@@ -16,7 +16,7 @@
unsigned long debug_enable_flags;
static struct kmem_cache *iscsi_cmnd_cache;
-static char dummy_data[1024];
+static u8 dummy_data[PAGE_SIZE];
static int ctr_major;
static char ctr_name[] = "ietctl";
@@ -726,13 +726,18 @@
case READ_10:
case WRITE_10:
case WRITE_VERIFY:
- *off = be32_to_cpu(*(u32 *)&cmd[2]);
+ *off = (u32)cmd[2] << 24 | (u32)cmd[3] << 16 |
+ (u32)cmd[4] << 8 | (u32)cmd[5];
*len = (cmd[7] << 8) + cmd[8];
break;
case READ_16:
case WRITE_16:
- *off = be64_to_cpu(*(u64 *)&cmd[2]);
- *len = be32_to_cpu(*(u32 *)&cmd[10]);
+ *off = (u64)cmd[2] << 56 | (u64)cmd[3] << 48 |
+ (u64)cmd[4] << 40 | (u64)cmd[5] << 32 |
+ (u64)cmd[6] << 24 | (u64)cmd[7] << 16 |
+ (u64)cmd[8] << 8 | (u64)cmd[9];
+ *len = (u32)cmd[10] << 24 | (u32)cmd[11] << 16 |
+ (u32)cmd[12] << 8 | (u32)cmd[13];
break;
default:
BUG();
Index: kernel/null-io.c
===================================================================
--- kernel/null-io.c (revision 138)
+++ kernel/null-io.c (working copy)
@@ -7,9 +7,10 @@
* data. It is only for performance measurement purpose.
*/
+#include <linux/types.h>
#include <linux/blkdev.h>
+#include <linux/parser.h>
#include <linux/writeback.h>
-#include <linux/parser.h>
#include "iscsi.h"
#include "iscsi_dbg.h"
Index: kernel/iscsi.h
===================================================================
--- kernel/iscsi.h (revision 138)
+++ kernel/iscsi.h (working copy)
@@ -11,8 +11,8 @@
#include <linux/seq_file.h>
#include <linux/mm.h>
#include <linux/crypto.h>
+#include <linux/scatterlist.h>
#include <net/sock.h>
-#include <asm/scatterlist.h>
#include "iscsi_hdr.h"
#include "iet_u.h"
@@ -66,6 +66,7 @@
void (*old_state_change)(struct sock *);
void (*old_data_ready)(struct sock *, int);
+ void (*old_write_space)(struct sock *);
};
struct worker_thread_info;
@@ -153,15 +154,21 @@
enum lu_flags {
LU_READONLY,
- LU_ASYNC,
+ LU_WCACHE,
+ LU_RCACHE,
};
#define LUReadonly(lu) test_bit(LU_READONLY, &(lu)->flags)
#define SetLUReadonly(lu) set_bit(LU_READONLY, &(lu)->flags)
-#define LUAsync(lu) test_bit(LU_ASYNC, &(lu)->flags)
-#define SetLUAsync(lu) set_bit(LU_ASYNC, &(lu)->flags)
+#define LUWCache(lu) test_bit(LU_WCACHE, &(lu)->flags)
+#define SetLUWCache(lu) set_bit(LU_WCACHE, &(lu)->flags)
+#define ClearLUWCache(lu) clear_bit(LU_WCACHE, &(lu)->flags)
+#define LURCache(lu) test_bit(LU_RCACHE, &(lu)->flags)
+#define SetLURCache(lu) set_bit(LU_RCACHE, &(lu)->flags)
+#define ClearLURCache(lu) clear_bit(LU_RCACHE, &(lu)->flags)
+
#define IET_HASH_ORDER 8
#define cmnd_hashfn(itt) hash_long((itt), IET_HASH_ORDER)
@@ -191,6 +198,7 @@
enum connection_state_bit {
CONN_ACTIVE,
CONN_CLOSING,
+ CONN_WSPACE_WAIT,
};
#define ISCSI_CONN_IOV_MAX (((256 << 10) >> PAGE_SHIFT) + 1)
@@ -300,6 +308,7 @@
extern int nthread_init(struct iscsi_target *);
extern int nthread_start(struct iscsi_target *);
extern int nthread_stop(struct iscsi_target *);
+extern void __nthread_wakeup(struct network_thread_info *);
extern void nthread_wakeup(struct iscsi_target *);
/* wthread.c */
Index: kernel/digest.c
===================================================================
--- kernel/digest.c (revision 138)
+++ kernel/digest.c (working copy)
@@ -4,8 +4,7 @@
* This code is licensed under the GPL.
*/
-#include <asm/types.h>
-#include <asm/scatterlist.h>
+#include <linux/types.h>
#include "iscsi.h"
#include "digest.h"
@@ -161,22 +160,17 @@
}
}
-/* Copied from linux-iscsi initiator and slightly adjusted */
-#define SETSG(sg, p, l) do { \
- (sg).page = virt_to_page((p)); \
- (sg).offset = ((unsigned long)(p) & ~PAGE_CACHE_MASK); \
- (sg).length = (l); \
-} while (0)
-
static void digest_header(struct hash_desc *hash, struct iscsi_pdu *pdu,
u8 *crc)
{
struct scatterlist sg[2];
unsigned int nbytes = sizeof(struct iscsi_hdr);
- SETSG(sg[0], &pdu->bhs, nbytes);
+ sg_init_table(sg, pdu->ahssize ? 2 : 1);
+
+ sg_set_buf(&sg[0], &pdu->bhs, nbytes);
if (pdu->ahssize) {
- SETSG(sg[1], pdu->ahs, pdu->ahssize);
+ sg_set_buf(&sg[1], pdu->ahs, pdu->ahssize);
nbytes += pdu->ahssize;
}
@@ -220,6 +214,7 @@
assert(count <= ISCSI_CONN_IOV_MAX);
+ sg_init_table(sg, ARRAY_SIZE(cmnd->conn->hash_sg));
crypto_hash_init(hash);
for (i = 0; size; i++) {
@@ -228,13 +223,13 @@
else
length = size;
- sg[i].page = tio->pvec[idx + i];
- sg[i].offset = offset;
- sg[i].length = length;
+ sg_set_page(&sg[i], tio->pvec[idx + i], length, offset);
size -= length;
offset = 0;
}
+ sg_mark_end(&sg[i - 1]);
+
crypto_hash_update(hash, sg, nbytes);
crypto_hash_final(hash, crc);
}
Index: kernel/event.c
===================================================================
--- kernel/event.c (revision 138)
+++ kernel/event.c (working copy)
@@ -28,7 +28,7 @@
return 0;
}
-static int event_recv_skb(struct sk_buff *skb)
+static void event_recv_skb(struct sk_buff *skb)
{
int err;
struct nlmsghdr *nlh;
@@ -37,7 +37,7 @@
while (skb->len >= NLMSG_SPACE(0)) {
nlh = (struct nlmsghdr *)skb->data;
if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
- return 0;
+ break;
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
if (rlen > skb->len)
rlen = skb->len;
@@ -47,21 +47,8 @@
netlink_ack(skb, nlh, 0);
skb_pull(skb, rlen);
}
- return 0;
}
-static void event_recv(struct sock *sk, int length)
-{
- struct sk_buff *skb;
-
- while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
- if (event_recv_skb(skb) && skb->len)
- skb_queue_head(&sk->sk_receive_queue, skb);
- else
- kfree_skb(skb);
- }
-}
-
static int notify(void *data, int len, int gfp_mask)
{
struct sk_buff *skb;
@@ -95,8 +82,8 @@
int event_init(void)
{
- nl = netlink_kernel_create(NETLINK_IET, 1, event_recv, NULL,
- THIS_MODULE);
+ nl = netlink_kernel_create(&init_net, NETLINK_IET, 1, event_recv_skb,
+ NULL, THIS_MODULE);
if (!nl)
return -ENOMEM;
else
Index: kernel/file-io.c
===================================================================
--- kernel/file-io.c (revision 138)
+++ kernel/file-io.c (working copy)
@@ -4,9 +4,10 @@
* This code is licenced under the GPL.
*/
+#include <linux/types.h>
#include <linux/blkdev.h>
+#include <linux/parser.h>
#include <linux/writeback.h>
-#include <linux/parser.h>
#include "iscsi.h"
#include "iscsi_dbg.h"
@@ -184,6 +185,7 @@
static int parse_fileio_params(struct iet_volume *volume, char *params)
{
+ struct fileio_data *info = volume->private;
int err = 0;
char *p, *q;
@@ -215,6 +217,13 @@
goto out;
break;
case Opt_path:
+ if (info->path) {
+ iprintk("Target %s, LUN %u: "
+ "duplicate \"Path\" param\n",
+ volume->target->name, volume->lun);
+ err = -EINVAL;
+ goto out;
+ }
if (!(q = match_strdup(&args[0]))) {
err = -ENOMEM;
goto out;
@@ -227,11 +236,17 @@
case Opt_ignore:
break;
default:
- eprintk("Unknown %s\n", p);
+ iprintk("Target %s, LUN %u: unknown param %s\n",
+ volume->target->name, volume->lun, p);
return -EINVAL;
}
}
+ if (!info->path) {
+ iprintk("Target %s, LUN %u: missing \"Path\" param\n",
+ volume->target->name, volume->lun);
+ err = -EINVAL;
+ }
out:
return err;
}
@@ -284,6 +299,8 @@
lu->blk_shift = SECTOR_SIZE_BITS;
lu->blk_cnt = inode->i_size >> lu->blk_shift;
+ /* we're using the page cache */
+ SetLURCache(lu);
out:
if (err < 0)
fileio_detach(lu);
Index: kernel/nthread.c
===================================================================
--- kernel/nthread.c (revision 138)
+++ kernel/nthread.c (working copy)
@@ -18,13 +18,18 @@
D_DATA_READY,
};
+void __nthread_wakeup(struct network_thread_info *info)
+{
+ set_bit(D_DATA_READY, &info->flags);
+ wake_up_process(info->task);
+}
+
void nthread_wakeup(struct iscsi_target *target)
{
struct network_thread_info *info = &target->nthread_info;
spin_lock_bh(&info->nthread_lock);
- set_bit(D_DATA_READY, &info->flags);
- wake_up_process(info->task);
+ __nthread_wakeup(info);
spin_unlock_bh(&info->nthread_lock);
}
@@ -283,6 +288,23 @@
return 0;
}
+/*
+ * @locking: grabs the target's nthread_lock to protect it from races with
+ * iet_write_space()
+ */
+static void set_conn_wspace_wait(struct iscsi_conn *conn)
+{
+ struct network_thread_info *info = &conn->session->target->nthread_info;
+ struct sock *sk = conn->sock->sk;
+
+ spin_lock_bh(&info->nthread_lock);
+
+ if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))
+ set_bit(CONN_WSPACE_WAIT, &conn->state);
+
+ spin_unlock_bh(&info->nthread_lock);
+}
+
/* This is taken from the Ardis code. */
static int write_data(struct iscsi_conn *conn)
{
@@ -399,8 +421,11 @@
conn->write_offset = (idx << PAGE_CACHE_SHIFT) + offset;
out_iov:
conn->write_size = size;
- if ((saved_size == size) && res == -EAGAIN)
- return res;
+ if (res == -EAGAIN) {
+ set_conn_wspace_wait(conn);
+ if (saved_size == size)
+ return res;
+ }
return saved_size - size;
@@ -557,6 +582,9 @@
goto out;
}
+ if (test_bit(CONN_WSPACE_WAIT, &conn->state))
+ goto out;
+
res = send(conn);
if (!list_empty(&conn->write_list) || conn->write_cmnd)
@@ -572,6 +600,7 @@
static void close_conn(struct iscsi_conn *conn)
{
struct iscsi_session *session = conn->session;
+ struct iscsi_target *target = session->target;
struct iscsi_cmnd *cmnd;
assert(conn);
@@ -579,8 +608,9 @@
conn->sock->ops->shutdown(conn->sock, 2);
write_lock_bh(&conn->sock->sk->sk_callback_lock);
- conn->sock->sk->sk_state_change = session->target->nthread_info.old_state_change;
- conn->sock->sk->sk_data_ready = session->target->nthread_info.old_data_ready;
+ conn->sock->sk->sk_state_change = target->nthread_info.old_state_change;
+ conn->sock->sk->sk_data_ready = target->nthread_info.old_data_ready;
+ conn->sock->sk->sk_write_space = target->nthread_info.old_write_space;
write_unlock_bh(&conn->sock->sk->sk_callback_lock);
fput(conn->file);
@@ -604,11 +634,11 @@
assert(0);
}
- event_send(session->target->tid, session->sid, conn->cid, E_CONN_CLOSE, 0);
+ event_send(target->tid, session->sid, conn->cid, E_CONN_CLOSE, 0);
conn_free(conn);
if (list_empty(&session->conn_list))
- session_del(session->target, session->sid);
+ session_del(target, session->sid);
}
static int istd(void *arg)
@@ -654,6 +684,7 @@
info->old_state_change = NULL;
info->old_data_ready = NULL;
+ info->old_write_space = NULL;
INIT_LIST_HEAD(&info->active_conns);
Index: kernel/conn.c
===================================================================
--- kernel/conn.c (revision 138)
+++ kernel/conn.c (working copy)
@@ -96,6 +96,28 @@
target->nthread_info.old_data_ready(sk, len);
}
+/*
+ * @locking: grabs the target's nthread_lock to protect it from races with
+ * set_conn_wspace_wait()
+ */
+static void iet_write_space(struct sock *sk)
+{
+ struct iscsi_conn *conn = sk->sk_user_data;
+ struct network_thread_info *info = &conn->session->target->nthread_info;
+
+ spin_lock_bh(&info->nthread_lock);
+
+ if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) &&
+ test_bit(CONN_WSPACE_WAIT, &conn->state)) {
+ clear_bit(CONN_WSPACE_WAIT, &conn->state);
+ __nthread_wakeup(info);
+ }
+
+ spin_unlock_bh(&info->nthread_lock);
+
+ info->old_write_space(sk);
+}
+
static void iet_socket_bind(struct iscsi_conn *conn)
{
int opt = 1;
@@ -114,6 +136,9 @@
target->nthread_info.old_data_ready = conn->sock->sk->sk_data_ready;
conn->sock->sk->sk_data_ready = iet_data_ready;
+
+ target->nthread_info.old_write_space = conn->sock->sk->sk_write_space;
+ conn->sock->sk->sk_write_space = iet_write_space;
write_unlock_bh(&conn->sock->sk->sk_callback_lock);
oldfs = get_fs();
Index: include/iet_u.h
===================================================================
--- include/iet_u.h (revision 138)
+++ include/iet_u.h (working copy)
@@ -1,7 +1,7 @@
#ifndef _IET_U_H
#define _IET_U_H
-#define IET_VERSION_STRING "0.4.15"
+#define IET_VERSION_STRING "0.4.16"
/* The maximum length of 223 bytes in the RFC. */
#define ISCSI_NAME_LEN 256
Index: doc/manpages/ietadm.8
===================================================================
--- doc/manpages/ietadm.8 (revision 138)
+++ doc/manpages/ietadm.8 (working copy)
@@ -154,7 +154,7 @@
create dynamically a new target, numbered 2. \s-1CAUTION\s0 : the target will disappear if you restart ietd, you'll have to edit /etc/ietd.conf to make it permanent!
.SH "ERROR MESSAGES"
.IX Header "ERROR MESSAGES"
-ietadm misses error messages. Look carefully the \s-1STDERR\s0 output : in case of error
+ietadm misses error messages. Look carefully at the \s-1STDERR\s0 output : in case of error
it will send a 3 number error code, ending with \-1, for instance :
.PP
ietd_request 203 3 \-1
@@ -216,6 +216,17 @@
If you don't specify a target (omit \-\-tid option),
you add a new account for discovery sessions.
.PP
+\&\fB\-\-op show \-\-tid=[id] \-\-user\fR
+.PP
+show a list of CHAP accounts.
+If \-\-tid is omitted or [id] is \*(L"0\*(R" (zero), discovery accounts are displayed.
+.PP
+\&\fB\-\-op show \-\-tid=[id] \-\-user \-\-params=[user]=[name]\fR
+.PP
+show CHAP account information for the account specified by [name].
+[user] can be [IncomingUser] or [OutgoingUser].
+If \-\-tid is omitted or [id] is \*(L"0\*(R" (zero), [name] is supposed to be a discovery account name.
+.PP
\&\fB\-\-op delete \-\-tid=[id] \-\-user \-\-params=[user]=[name]\fR
.PP
delete specific account having [name] of specific
Index: doc/manpages/ietd.conf.5
===================================================================
--- doc/manpages/ietd.conf.5 (revision 138)
+++ doc/manpages/ietd.conf.5 (working copy)
@@ -202,7 +202,7 @@
Optional. If set to "CRC32C" and the initiator is configured accordingly, the integrity of an iSCSI PDU's data segment will be protected by a CRC32C checksum. The default is "None". Note that data digests are not supported during discovery sessions.
.TP
.B [MaxConnections <value>]
-Optional. Has to be set to "1" (in words: one), which is also the default.
+Optional. The number of connections within a session. Has to be set to "1" (in words: one), which is also the default since MC/S is not supported.
.TP
.B [InitialR2T <Yes|No>]
Optional. If set to "Yes" (default), the initiator has to wait for the target to solicit SCSI data before sending it. Setting it to "No" allows the initiator to send a burst of
Index: ChangeLog
===================================================================
--- ChangeLog (revision 138)
+++ ChangeLog (working copy)
@@ -1,3 +1,29 @@
+Summary of changes from v0.4.15 to v0.4.16
+=================================
+
+Arne Redlich
+ o fix overzealous assert() in digest_data()
+ o add checking on return value of ISCSI_PARAM_GET
+ o 2.6.22, 2.6.23 and 2.6.24 compile fixes
+ o add conn->rwsize check
+ o avoid potential NULL-ptr dereferences in rx and tx buffer
+ o fix the shell syntax in init scripts
+
+Dave Jiang
+ o fix digest endieness on LE archs
+
+FUJITA Tomonori
+ o fix SPARC alignement issues (based on a patch from joel.bertrand@systella.fr)
+
+Ross S. W. Walker
+ o fix DISTDIR in Makefile for /etc install
+ o add support to nullio for volumes > 2TB
+ o remove init.d memory size adjustment
+ o add error code reporting to blockio_open_path
+ o blockio gen_scsiid bug fix
+ o add verbosity to kernel output and task management
+
+
Summary of changes from v0.4.14 to v0.4.15
=================================
Index: patches/compat-2.6.22-2.6.23.patch
===================================================================
--- patches/compat-2.6.22-2.6.23.patch (revision 0)
+++ patches/compat-2.6.22-2.6.23.patch (revision 174)
@@ -0,0 +1,152 @@
+Index: kernel/block-io.c
+===================================================================
+--- kernel/block-io.c (working copy)
++++ kernel/block-io.c (revision 145)
+@@ -28,10 +28,15 @@ struct tio_work {
+ struct completion tio_complete;
+ };
+
+-static void blockio_bio_endio(struct bio *bio, int error)
++static int
++blockio_bio_endio(struct bio *bio, unsigned int bytes_done, int error)
+ {
+ struct tio_work *tio_work = bio->bi_private;
+
++ /* Ignore partials */
++ if (bio->bi_size)
++ return 1;
++
+ error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO;
+
+ if (error)
+@@ -42,6 +47,8 @@ static void blockio_bio_endio(struct bio
+ complete(&tio_work->tio_complete);
+
+ bio_put(bio);
++
++ return 0;
+ }
+
+ /*
+Index: kernel/config.c
+===================================================================
+--- kernel/config.c (working copy)
++++ kernel/config.c (revision 145)
+@@ -40,7 +40,7 @@ int iet_procfs_init(void)
+ int i;
+ struct proc_dir_entry *ent;
+
+- if (!(proc_iet_dir = proc_mkdir("iet", init_net.proc_net)))
++ if (!(proc_iet_dir = proc_mkdir("net/iet", 0)))
+ goto err;
+
+ proc_iet_dir->owner = THIS_MODULE;
+Index: kernel/digest.c
+===================================================================
+--- kernel/digest.c (working copy)
++++ kernel/digest.c (revision 145)
+@@ -161,17 +161,22 @@ static inline void __dbg_simulate_data_d
+ }
+ }
+
++/* Copied from linux-iscsi initiator and slightly adjusted */
++#define SETSG(sg, p, l) do { \
++ (sg).page = virt_to_page((p)); \
++ (sg).offset = ((unsigned long)(p) & ~PAGE_CACHE_MASK); \
++ (sg).length = (l); \
++} while (0)
++
+ static void digest_header(struct hash_desc *hash, struct iscsi_pdu *pdu,
+ u8 *crc)
+ {
+ struct scatterlist sg[2];
+ unsigned int nbytes = sizeof(struct iscsi_hdr);
+
+- sg_init_table(sg, pdu->ahssize ? 2 : 1);
+-
+- sg_set_buf(&sg[0], &pdu->bhs, nbytes);
++ SETSG(sg[0], &pdu->bhs, nbytes);
+ if (pdu->ahssize) {
+- sg_set_buf(&sg[1], pdu->ahs, pdu->ahssize);
++ SETSG(sg[1], pdu->ahs, pdu->ahssize);
+ nbytes += pdu->ahssize;
+ }
+
+@@ -215,7 +220,6 @@ static void digest_data(struct hash_desc
+
+ assert(count <= ISCSI_CONN_IOV_MAX);
+
+- sg_init_table(sg, ARRAY_SIZE(cmnd->conn->hash_sg));
+ crypto_hash_init(hash);
+
+ for (i = 0; size; i++) {
+@@ -224,13 +228,13 @@ static void digest_data(struct hash_desc
+ else
+ length = size;
+
+- sg_set_page(&sg[i], tio->pvec[idx + i], length, offset);
++ sg[i].page = tio->pvec[idx + i];
++ sg[i].offset = offset;
++ sg[i].length = length;
+ size -= length;
+ offset = 0;
+ }
+
+- sg_mark_end(&sg[i - 1]);
+-
+ crypto_hash_update(hash, sg, nbytes);
+ crypto_hash_final(hash, crc);
+ }
+Index: kernel/event.c
+===================================================================
+--- kernel/event.c (working copy)
++++ kernel/event.c (revision 145)
+@@ -28,7 +28,7 @@ static int event_recv_msg(struct sk_buff
+ return 0;
+ }
+
+-static void event_recv_skb(struct sk_buff *skb)
++static int event_recv_skb(struct sk_buff *skb)
+ {
+ int err;
+ struct nlmsghdr *nlh;
+@@ -37,7 +37,7 @@ static void event_recv_skb(struct sk_buf
+ while (skb->len >= NLMSG_SPACE(0)) {
+ nlh = (struct nlmsghdr *)skb->data;
+ if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+- break;
++ return 0;
+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+ if (rlen > skb->len)
+ rlen = skb->len;
+@@ -47,6 +47,19 @@ static void event_recv_skb(struct sk_buf
+ netlink_ack(skb, nlh, 0);
+ skb_pull(skb, rlen);
+ }
++ return 0;
++}
++
++static void event_recv(struct sock *sk, int length)
++{
++ struct sk_buff *skb;
++
++ while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
++ if (event_recv_skb(skb) && skb->len)
++ skb_queue_head(&sk->sk_receive_queue, skb);
++ else
++ kfree_skb(skb);
++ }
+ }
+
+ static int notify(void *data, int len, int gfp_mask)
+@@ -82,8 +95,8 @@ int event_send(u32 tid, u64 sid, u32 cid
+
+ int event_init(void)
+ {
+- nl = netlink_kernel_create(&init_net, NETLINK_IET, 1, event_recv_skb,
+- NULL, THIS_MODULE);
++ nl = netlink_kernel_create(NETLINK_IET, 1, event_recv, NULL,
++ THIS_MODULE);
+ if (!nl)
+ return -ENOMEM;
+ else
Index: patches/compat-2.6.14-2.6.18.patch
===================================================================
--- patches/compat-2.6.14-2.6.18.patch (revision 138)
+++ patches/compat-2.6.14-2.6.18.patch (working copy)
@@ -199,7 +199,7 @@
-static struct kmem_cache *iscsi_cmnd_cache;
+static kmem_cache_t *iscsi_cmnd_cache;
- static char dummy_data[1024];
+ static u8 dummy_data[PAGE_SIZE];
static int ctr_major;
Index: kernel/tio.c
Index: usr/misc.h
===================================================================
--- usr/misc.h (revision 138)
+++ usr/misc.h (working copy)
@@ -5,9 +5,9 @@
#ifndef MISC_H
#define MISC_H
-struct qelem {
- struct qelem *q_forw;
- struct qelem *q_back;
+struct __qelem {
+ struct __qelem *q_forw;
+ struct __qelem *q_back;
};
/* stolen list stuff from Linux kernel */
@@ -21,20 +21,20 @@
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
- struct qelem name = LIST_HEAD_INIT(name)
+ struct __qelem name = LIST_HEAD_INIT(name)
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->q_forw = (ptr); (ptr)->q_back = (ptr); \
} while (0)
-static inline int list_empty(const struct qelem *head)
+static inline int list_empty(const struct __qelem *head)
{
return head->q_forw == head;
}
-static inline int list_length_is_one(const struct qelem *head)
+static inline int list_length_is_one(const struct __qelem *head)
{
- return head->q_forw == head->q_back;
+ return (!list_empty(head) && head->q_forw == head->q_back);
}
#define container_of(ptr, type, member) ({ \
Index: usr/ietadm.c
===================================================================
--- usr/ietadm.c (revision 138)
+++ usr/ietadm.c (working copy)
@@ -29,6 +29,8 @@
#define SET_LUNIT (1 << 3)
#define SET_USER (1 << 4)
+typedef int (user_handle_fn_t)(struct ietadm_req *req, char *user, char *pass);
+
enum ietadm_op {
OP_NEW,
OP_DELETE,
@@ -72,6 +74,14 @@
show iSCSI parameters in effect for session [sid]. If\n\
[sid] is \"0\" (zero), the configured parameters\n\
will be displayed.\n\
+ --op show --tid=[id] --user\n\
+ show list of Discovery (--tid omitted / id=0 (zero))\n\
+ or target CHAP accounts.\n\
+ --op show --tid=[id] --user --params=[user]=[name]\n\
+ show CHAP account information. [user] can be\n\
+ \"IncomingUser\" or \"OutgoingUser\". If --tid is\n\
+ omitted / id=0 (zero), [user] is treated as Discovery\n\
+ user.\n\
--op new --tid=[id] --lun=[lun] --params Path=[path]\n\
add a new logical unit with [lun] to specific\n\
target with [id]. The logical unit is offered\n\
@@ -142,7 +152,8 @@
return err;
}
-static int ietd_response_recv(int fd, struct ietadm_req *req)
+static int ietd_response_recv(int fd, struct ietadm_req *req, void *rsp_data,
+ size_t rsp_data_sz)
{
int err, ret;
struct iovec iov[2];
@@ -161,6 +172,15 @@
} else
err = rsp.err;
+ if (!err && rsp_data_sz && rsp_data) {
+ ret = read(fd, rsp_data, rsp_data_sz);
+ if (ret != rsp_data_sz) {
+ err = (ret < 0) ? -errno : -EIO;
+ fprintf(stderr, "%s %d %d %d\n", __FUNCTION__,
+ __LINE__, ret, err);
+ }
+ }
+
return err;
}
@@ -183,7 +203,8 @@
return fd;
}
-static int ietd_request(struct ietadm_req *req)
+static int ietd_request(struct ietadm_req *req, void *rsp_data,
+ size_t rsp_data_sz)
{
int fd = -1, err = -EIO;
@@ -195,7 +216,7 @@
if ((err = ietd_request_send(fd, req)) < 0)
goto out;
- err = ietd_response_recv(fd, req);
+ err = ietd_response_recv(fd, req, rsp_data, rsp_data_sz);
out:
if (fd > 0)
@@ -318,7 +339,7 @@
break;
}
- err = ietd_request(&req);
+ err = ietd_request(&req, NULL, 0);
if (!err && req.rcmnd == C_TRGT_SHOW)
show_iscsi_param(key_target, req.u.trgt.target_param);
@@ -357,7 +378,7 @@
break;
}
- err = ietd_request(&req);
+ err = ietd_request(&req, NULL, 0);
out:
return err;
}
@@ -385,7 +406,7 @@
break;
case OP_SHOW:
req.rcmnd = C_SESS_SHOW;
- err = ietd_request(&req);
+ err = ietd_request(&req, NULL, 0);
if (!err)
show_iscsi_param(key_session, req.u.trgt.session_param);
break;
@@ -395,31 +416,11 @@
return err;
}
-static int user_handle(int op, u32 set, u32 tid, char *params)
+static int parse_user_params(char *params, u32 *auth_dir, char **user,
+ char **pass)
{
- int err = -EINVAL;
- char *p, *q, *user = NULL, *pass = NULL;
- struct ietadm_req req;
+ char *p, *q;
- if (set & ~(SET_TARGET | SET_USER))
- goto out;
-
- memset(&req, 0, sizeof(req));
- req.tid = tid;
-
- switch (op) {
- case OP_NEW:
- req.rcmnd = C_ACCT_NEW;
- break;
- case OP_DELETE:
- req.rcmnd = C_ACCT_DEL;
- break;
- case OP_UPDATE:
- case OP_SHOW:
- fprintf(stderr, "Unsupported.\n");
- goto out;
- }
-
while ((p = strsep(¶ms, ",")) != NULL) {
if (!*p)
continue;
@@ -431,37 +432,187 @@
q++;
if (!strcasecmp(p, "IncomingUser")) {
- if (user)
- fprintf(stderr, "Already specified user %s\n", q);
- user = q;
- req.u.acnt.auth_dir = AUTH_DIR_INCOMING;
+ if (*user)
+ fprintf(stderr,
+ "Already specified IncomingUser %s\n",
+ q);
+ *user = q;
+ *auth_dir = AUTH_DIR_INCOMING;
} else if (!strcasecmp(p, "OutgoingUser")) {
- if (user)
- fprintf(stderr, "Already specified user %s\n", q);
- user = q;
- req.u.acnt.auth_dir = AUTH_DIR_OUTGOING;
+ if (*user)
+ fprintf(stderr,
+ "Already specified OutgoingUser %s\n",
+ q);
+ *user = q;
+ *auth_dir = AUTH_DIR_OUTGOING;
} else if (!strcasecmp(p, "Password")) {
- if (pass)
- fprintf(stderr, "Already specified pass %s\n", q);
- pass = q;
+ if (*pass)
+ fprintf(stderr,
+ "Already specified Password %s\n", q);
+ *pass = q;
} else {
fprintf(stderr, "Unknown parameter %p\n", q);
- goto out;
+ return -EINVAL;
}
}
+ return 0;
+}
- if ((op == OP_NEW && ((user && !pass) || (!user && pass) || (!user && !pass))) ||
- (op == OP_DELETE && ((!user && pass) || (!user && !pass)))) {
- fprintf(stderr,
- "You need to specify a user and its password %s %s\n", pass, user);
- goto out;
+static void show_account(int auth_dir, char *user, char *pass)
+{
+ char buf[(ISCSI_NAME_LEN + 1) * 2] = {0};
+
+ snprintf(buf, ISCSI_NAME_LEN, "%s", user);
+ if (pass)
+ snprintf(buf + strlen(buf), ISCSI_NAME_LEN, " %s", pass);
+
+ printf("%sUser %s\n", (auth_dir == AUTH_DIR_INCOMING) ?
+ "Incoming" : "Outgoing", buf);
+}
+
+static int user_handle_show_user(struct ietadm_req *req, char *user)
+{
+ int err;
+
+ req->rcmnd = C_ACCT_SHOW;
+ strncpy(req->u.acnt.u.user.name, user,
+ sizeof(req->u.acnt.u.user.name) - 1);
+
+ err = ietd_request(req, NULL, 0);
+ if (!err)
+ show_account(req->u.acnt.auth_dir, req->u.acnt.u.user.name,
+ req->u.acnt.u.user.pass);
+
+ return err;
+}
+
+static int user_handle_show_list(struct ietadm_req *req)
+{
+ int i, err, retry;
+ size_t buf_sz = 0;
+ char *buf;
+
+ req->u.acnt.auth_dir = AUTH_DIR_INCOMING;
+ req->rcmnd = C_ACCT_LIST;
+
+ do {
+ retry = 0;
+
+ buf_sz = buf_sz ? buf_sz : ISCSI_NAME_LEN;
+
+ buf = calloc(buf_sz, sizeof(char *));
+ if (!buf) {
+ fprintf(stderr, "Memory allocation failed\n");
+ return -ENOMEM;
+ }
+
+ req->u.acnt.u.list.alloc_len = buf_sz;
+
+ err = ietd_request(req, buf, buf_sz);
+ if (err) {
+ free(buf);
+ break;
+ }
+
+ if (req->u.acnt.u.list.overflow) {
+ buf_sz = ISCSI_NAME_LEN * (req->u.acnt.u.list.count +
+ req->u.acnt.u.list.overflow);
+ retry = 1;
+ free(buf);
+ continue;
+ }
+
+ for (i = 0; i < req->u.acnt.u.list.count; i++)
+ show_account(req->u.acnt.auth_dir,
+ &buf[i * ISCSI_NAME_LEN], NULL);
+
+ if (req->u.acnt.auth_dir == AUTH_DIR_INCOMING) {
+ req->u.acnt.auth_dir = AUTH_DIR_OUTGOING;
+ buf_sz = 0;
+ retry = 1;
+ }
+
+ free(buf);
+
+ } while (retry);
+
+ return err;
+}
+
+static int user_handle_show(struct ietadm_req *req, char *user, char *pass)
+{
+ if (pass)
+ fprintf(stderr, "Ignoring specified password\n");
+
+ if (user)
+ return user_handle_show_user(req, user);
+ else
+ return user_handle_show_list(req);
+}
+
+static int user_handle_new(struct ietadm_req *req, char *user, char *pass)
+{
+ if (!user || !pass) {
+ fprintf(stderr, "Username and password must be specified\n");
+ return -EINVAL;
}
- strncpy(req.u.acnt.user, user, sizeof(req.u.acnt.user) - 1);
+ req->rcmnd = C_ACCT_NEW;
+
+ strncpy(req->u.acnt.u.user.name, user,
+ sizeof(req->u.acnt.u.user.name) - 1);
+ strncpy(req->u.acnt.u.user.pass, pass,
+ sizeof(req->u.acnt.u.user.pass) - 1);
+
+ return ietd_request(req, NULL, 0);
+}
+
+static int user_handle_del(struct ietadm_req *req, char *user, char *pass)
+{
+ if (!user) {
+ fprintf(stderr, "Username must be specified\n");
+ return -EINVAL;
+ }
if (pass)
- strncpy(req.u.acnt.pass, pass, sizeof(req.u.acnt.pass) - 1);
+ fprintf(stderr, "Ignoring specified password\n");
- err = ietd_request(&req);
+ req->rcmnd = C_ACCT_DEL;
+
+ strncpy(req->u.acnt.u.user.name, user,
+ sizeof(req->u.acnt.u.user.name) - 1);
+
+ return ietd_request(req, NULL, 0);
+}
+
+static int user_handle(int op, u32 set, u32 tid, char *params)
+{
+ int err = -EINVAL;
+ char *user = NULL, *pass = NULL;
+ struct ietadm_req req;
+ static user_handle_fn_t *user_handle_fn[] = {
+ user_handle_new,
+ user_handle_del,
+ NULL,
+ user_handle_show,
+ }, *fn;
+
+ if (set & ~(SET_TARGET | SET_USER))
+ goto out;
+
+ memset(&req, 0, sizeof(req));
+ req.tid = tid;
+
+ err = parse_user_params(params, &req.u.acnt.auth_dir, &user, &pass);
+ if (err)
+ goto out;
+
+ fn = user_handle_fn[op];
+ if (!fn) {
+ fprintf(stderr, "Unsupported\n");
+ goto out;
+ }
+
+ err = fn(&req, user, pass);
out:
return err;
}
@@ -494,7 +645,7 @@
break;
}
- err = ietd_request(&req);
+ err = ietd_request(&req, NULL, 0);
out:
return err;
}
@@ -518,7 +669,7 @@
break;
}
- err = ietd_request(&req);
+ err = ietd_request(&req, NULL, 0);
return err;
}
Index: usr/plain.c
===================================================================
--- usr/plain.c (revision 138)
+++ usr/plain.c (working copy)
@@ -31,7 +31,7 @@
*/
struct user {
- struct qelem ulist;
+ struct __qelem ulist;
u32 tid;
char *name;
@@ -62,18 +62,18 @@
{NULL,},
};
-static struct qelem discovery_users_in = LIST_HEAD_INIT(discovery_users_in);
-static struct qelem discovery_users_out = LIST_HEAD_INIT(discovery_users_out);
+static struct __qelem discovery_users_in = LIST_HEAD_INIT(discovery_users_in);
+static struct __qelem discovery_users_out = LIST_HEAD_INIT(discovery_users_out);
#define HASH_ORDER 4
#define acct_hash(x) ((x) & ((1 << HASH_ORDER) - 1))
-static struct qelem trgt_acct_in[1 << HASH_ORDER];
-static struct qelem trgt_acct_out[1 << HASH_ORDER];
+static struct __qelem trgt_acct_in[1 << HASH_ORDER];
+static struct __qelem trgt_acct_out[1 << HASH_ORDER];
-static struct qelem *account_list_get(u32 tid, int dir)
+static struct __qelem *account_list_get(u32 tid, int dir)
{
- struct qelem *list = NULL;
+ struct __qelem *list = NULL;
if (tid) {
list = (dir == AUTH_DIR_INCOMING) ?
@@ -125,7 +125,7 @@
/* Return the first account if the length of name is zero */
static struct user *account_lookup_by_name(u32 tid, int dir, char *name)
{
- struct qelem *list = account_list_get(tid, dir);
+ struct __qelem *list = account_list_get(tid, dir);
struct user *user = NULL;
list_for_each_entry(user, list, ulist) {
@@ -156,6 +156,30 @@
return 0;
}
+static int plain_account_list(u32 tid, int dir, u32 *cnt, u32 *overflow,
+ char *buf, size_t buf_sz)
+{
+ struct __qelem *list = account_list_get(tid, dir);
+ struct user *user;
+
+ *cnt = *overflow = 0;
+
+ if (!list)
+ return -ENOENT;
+
+ list_for_each_entry(user, list, ulist) {
+ if (buf_sz >= ISCSI_NAME_LEN) {
+ strncpy(buf, user->name, ISCSI_NAME_LEN);
+ buf_sz -= ISCSI_NAME_LEN;
+ buf += ISCSI_NAME_LEN;
+ *cnt += 1;
+ } else
+ *overflow += 1;
+ }
+
+ return 0;
+}
+
static void account_destroy(struct user *user)
{
if (!user)
@@ -196,7 +220,7 @@
{
int err = -ENOMEM;
struct user *user;
- struct qelem *list;
+ struct __qelem *list;
if (!name || !pass)
return -EINVAL;
@@ -220,7 +244,7 @@
" Replacing the old one.\n",
tid ? "target" : "discovery");
- old = (struct user *) list->q_forw;
+ old = list_entry(list->q_forw, struct user, ulist);
account_destroy(old);
}
@@ -617,5 +641,6 @@
.account_add = plain_account_add,
.account_del = plain_account_del,
.account_query = plain_account_query,
+ .account_list = plain_account_list,
.initiator_access = plain_initiator_access,
};
Index: usr/ietadm.h
===================================================================
--- usr/ietadm.h (revision 138)
+++ usr/ietadm.h (working copy)
@@ -16,8 +16,17 @@
struct msg_acnt {
u32 auth_dir;
- char user[ISCSI_NAME_LEN];
- char pass[ISCSI_NAME_LEN];
+ union {
+ struct {
+ char name[ISCSI_NAME_LEN];
+ char pass[ISCSI_NAME_LEN];
+ } user;
+ struct {
+ u32 alloc_len;
+ u32 count;
+ u32 overflow;
+ } list;
+ } u;
};
struct msg_lunit {
@@ -54,6 +63,8 @@
C_SYS_DEL,
C_SYS_UPDATE,
C_SYS_SHOW,
+
+ C_ACCT_LIST,
};
struct ietadm_req {
Index: usr/config.h
===================================================================
--- usr/config.h (revision 138)
+++ usr/config.h (working copy)
@@ -14,6 +14,7 @@
int (*account_add) (u32, int, char *, char *);
int (*account_del) (u32, int, char *);
int (*account_query) (u32, int, char *, char *);
+ int (*account_list) (u32, int, u32 *, u32 *, char *, size_t);
int (*initiator_access) (u32, int);
};
Index: usr/isns.c
===================================================================
--- usr/isns.c (revision 138)
+++ usr/isns.c (working copy)
@@ -44,12 +44,12 @@
struct isns_qry_mgmt {
char name[ISCSI_NAME_LEN];
uint16_t transaction;
- struct qelem qlist;
+ struct __qelem qlist;
};
struct isns_initiator {
char name[ISCSI_NAME_LEN];
- struct qelem ilist;
+ struct __qelem ilist;
};
static LIST_HEAD(qry_list);
Index: usr/iscsid.c
===================================================================
--- usr/iscsid.c (revision 138)
+++ usr/iscsid.c (working copy)
@@ -98,7 +98,7 @@
}
conn->rsp.data = conn->rsp_buffer;
}
- if (conn->rwsize + len > INCOMING_BUFSIZE) {
+ if (conn->rsp.datasize + len > INCOMING_BUFSIZE) {
log_warning("Dropping key (%s=%s)", key, value);
return;
}
Index: usr/log.c
===================================================================
--- usr/log.c (revision 138)
+++ usr/log.c (working copy)
@@ -62,15 +62,24 @@
}
}
+/* Definition for log_pdu buffer */
+#define BUFFER_SIZE 16
+
+/*
+ * size required for a hex dump of BUFFER_SIZE bytes (' ' + 2 chars = 3 chars
+ * per byte) with a ' |' separator each 4th byte:
+ */
+#define LINE_SIZE (BUFFER_SIZE * 3 + BUFFER_SIZE / 4 * 2 + 1)
+
static void __dump_line(int level, unsigned char *buf, int *cp)
{
- char line[16*3+5], *lp = line;
+ char line[LINE_SIZE], *lp = line;
int i, cnt;
cnt = *cp;
if (!cnt)
return;
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < BUFFER_SIZE; i++) {
if (i < cnt)
lp += sprintf(lp, " %02x", buf[i]);
else
@@ -80,7 +89,9 @@
if (i >= cnt || !isprint(buf[i]))
buf[i] = ' ';
}
- log_debug(level, "%s %.16s |", line, buf);
+
+ /* buf is not \0-terminated! */
+ log_debug(level, "%s %.*s |", line, BUFFER_SIZE, buf);
*cp = 0;
}
@@ -89,7 +100,7 @@
int cnt = (*cp)++;
buf[cnt] = ch;
- if (cnt == 15)
+ if (cnt == BUFFER_SIZE - 1)
__dump_line(level, buf, cp);
}
@@ -98,13 +109,12 @@
void log_pdu(int level, struct PDU *pdu)
{
- unsigned char char_buf[16];
+ unsigned char char_buf[BUFFER_SIZE];
int char_cnt = 0;
unsigned char *buf;
int i;
- return;
- if (log_level <= level)
+ if (log_level < level)
return;
buf = (void *)&pdu->bhs;
Index: usr/iscsid.h
===================================================================
--- usr/iscsid.h (revision 138)
+++ usr/iscsid.h (working copy)
@@ -32,7 +32,7 @@
#define KEY_STATE_DONE 2
struct session {
- struct qelem slist;
+ struct __qelem slist;
char *initiator;
struct target *target;
@@ -122,9 +122,9 @@
#define INCOMING_BUFSIZE 8192
struct target {
- struct qelem tlist;
+ struct __qelem tlist;
- struct qelem sessions_list;
+ struct __qelem sessions_list;
u32 tid;
char name[ISCSI_NAME_LEN];
@@ -133,7 +133,7 @@
int max_nr_sessions;
int nr_sessions;
- struct qelem isns_head;
+ struct __qelem isns_head;
};
/* chap.c */
@@ -180,7 +180,7 @@
extern void session_remove(struct session *session);
/* target.c */
-extern struct qelem targets_list;
+extern struct __qelem targets_list;
extern int target_add(u32 *, char *);
extern int target_del(u32);
extern u32 target_find_by_name(const char *name);
Index: usr/message.c
===================================================================
--- usr/message.c (revision 138)
+++ usr/message.c (working copy)
@@ -6,6 +6,7 @@
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
@@ -37,7 +38,8 @@
return fd;
}
-static void ietadm_request_exec(struct ietadm_req *req, struct ietadm_rsp *rsp)
+static void ietadm_request_exec(struct ietadm_req *req, struct ietadm_rsp *rsp,
+ void **rsp_data, size_t *rsp_data_sz)
{
int err = 0;
@@ -99,14 +101,35 @@
break;
case C_ACCT_NEW:
- err = cops->account_add(req->tid, req->u.acnt.auth_dir, req->u.acnt.user,
- req->u.acnt.pass);
+ err = cops->account_add(req->tid, req->u.acnt.auth_dir,
+ req->u.acnt.u.user.name,
+ req->u.acnt.u.user.pass);
break;
case C_ACCT_DEL:
- err = cops->account_del(req->tid, req->u.acnt.auth_dir, req->u.acnt.user);
+ err = cops->account_del(req->tid, req->u.acnt.auth_dir,
+ req->u.acnt.u.user.name);
break;
+ case C_ACCT_LIST:
+ *rsp_data = malloc(req->u.acnt.u.list.alloc_len);
+ if (!*rsp_data) {
+ err = -ENOMEM;
+ break;
+ }
+
+ *rsp_data_sz = req->u.acnt.u.list.alloc_len;
+ memset(*rsp_data, 0x0, *rsp_data_sz);
+
+ err = cops->account_list(req->tid, req->u.acnt.auth_dir,
+ &req->u.acnt.u.list.count,
+ &req->u.acnt.u.list.overflow,
+ *rsp_data, *rsp_data_sz);
+ break;
case C_ACCT_UPDATE:
+ break;
case C_ACCT_SHOW:
+ err = cops->account_query(req->tid, req->u.acnt.auth_dir,
+ req->u.acnt.u.user.name,
+ req->u.acnt.u.user.pass);
break;
case C_SYS_NEW:
break;
@@ -132,7 +155,9 @@
socklen_t len;
struct ietadm_req req;
struct ietadm_rsp rsp;
- struct iovec iov[2];
+ struct iovec iov[3];
+ void *rsp_data = NULL;
+ size_t rsp_data_sz;
memset(&rsp, 0, sizeof(rsp));
len = sizeof(addr);
@@ -162,17 +187,22 @@
goto out;
}
- ietadm_request_exec(&req, &rsp);
+ ietadm_request_exec(&req, &rsp, &rsp_data, &rsp_data_sz);
send:
iov[0].iov_base = &req;
iov[0].iov_len = sizeof(req);
iov[1].iov_base = &rsp;
iov[1].iov_len = sizeof(rsp);
+ iov[2].iov_base = rsp.err ? NULL : rsp_data;
+ iov[2].iov_len = iov[2].iov_base ? rsp_data_sz : 0;
- err = writev(fd, iov, 2);
+ err = writev(fd, iov, 2 + !!iov[2].iov_len);
out:
if (fd > 0)
close(fd);
+ if (rsp_data)
+ free(rsp_data);
+
return err;
}
Index: usr/target.c
===================================================================
--- usr/target.c (revision 138)
+++ usr/target.c (working copy)
@@ -14,7 +14,7 @@
#include "iscsid.h"
-struct qelem targets_list = LIST_HEAD_INIT(targets_list);
+struct __qelem targets_list = LIST_HEAD_INIT(targets_list);
void target_list_build(struct connection *conn, char *addr, char *name)
{
Index: usr/Makefile
===================================================================
--- usr/Makefile (revision 138)
+++ usr/Makefile (working copy)
@@ -1,4 +1,5 @@
CFLAGS += -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include
+CFLAGS += -D_GNU_SOURCE # required for glibc >= 2.8
PROGRAMS = ietd ietadm
LIBS = -lcrypto
Index: Makefile
===================================================================
--- Makefile (revision 138)
+++ Makefile (working copy)
@@ -51,6 +51,11 @@
# base first the earlier patch sets will not need to be modified.
#
+# Compatibility patch for kernels >= 2.6.22 and <= 2.6.23
+ifeq ($(call kver_le,2,6,23),1)
+ PATCHES := $(PATCHES) compat-2.6.22-2.6.23.patch
+endif
+
# Compatibility patch for kernels >= 2.6.19 and <= 2.6.21
ifeq ($(call kver_le,2,6,21),1)
PATCHES := $(PATCHES) compat-2.6.19-2.6.21.patch