Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.1:kernel-2.6.32
iscsitarget
iscsitarget-svn-174.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
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
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor