From 7d18a8a3e2bef83942f3831b888521d6c119a529 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Thu, 31 Jan 2008 18:28:43 +0000 Subject: [PATCH] - Update to work on 2.6.24 - Minor cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@251 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/digest.c | 15 ++--- iscsi-scst/kernel/event.c | 26 +++++++-- iscsi-scst/kernel/iscsi.c | 15 ++--- iscsi-scst/kernel/nthread.c | 62 +++++++++++---------- qla2x00t/qla2x00-target/qla2x00t.c | 13 +++-- qla2x00t/qla2x00-target/qla2x00t.h | 6 +- qla2x00t/qla_attr.c | 4 +- scst/include/scsi_tgt.h | 88 +++++++++++++++++++++++++++++- scst/src/dev_handlers/scst_user.c | 11 ++-- scst/src/dev_handlers/scst_vdisk.c | 40 ++++++++++---- scst/src/scst_lib.c | 38 ------------- scst/src/scst_main.c | 3 +- scst/src/scst_mem.c | 60 +++++++++++--------- scst/src/scst_mem.h | 1 - scst/src/scst_targ.c | 8 +-- 15 files changed, 236 insertions(+), 154 deletions(-) diff --git a/iscsi-scst/kernel/digest.c b/iscsi-scst/kernel/digest.c index 6cef26364..8a2bf5c2d 100644 --- a/iscsi-scst/kernel/digest.c +++ b/iscsi-scst/kernel/digest.c @@ -56,13 +56,6 @@ int digest_init(struct iscsi_conn *conn) return 0; } -/* 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_MASK); \ - (sg).length = (l); \ -} while (0) - static u32 evaluate_crc32_from_sg(struct scatterlist *sg, int total, int pad_bytes) { @@ -80,7 +73,7 @@ static u32 evaluate_crc32_from_sg(struct scatterlist *sg, int total, int d = min(min(total, (int)(sg->length)), (int)(PAGE_SIZE - sg->offset)); - crc = crc32c(crc, page_address(sg->page) + sg->offset, d); + crc = crc32c(crc, sg_virt(sg), d); total -= d; sg++; } @@ -103,9 +96,11 @@ static u32 digest_header(struct iscsi_pdu *pdu) struct scatterlist sg[2]; unsigned int nbytes = sizeof(struct iscsi_hdr); - SETSG(sg[0], &pdu->bhs, nbytes); + sg_init_table(sg, 2); + + 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; } return evaluate_crc32_from_sg(sg, nbytes, 0); diff --git a/iscsi-scst/kernel/event.c b/iscsi-scst/kernel/event.c index 0a4575c9e..5e2cb2037 100644 --- a/iscsi-scst/kernel/event.c +++ b/iscsi-scst/kernel/event.c @@ -39,7 +39,11 @@ static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return 0; } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) static int event_recv_skb(struct sk_buff *skb) +#else +static void event_recv_skb(struct sk_buff *skb) +#endif { int err; struct nlmsghdr *nlh; @@ -48,7 +52,7 @@ static int event_recv_skb(struct sk_buff *skb) while (skb->len >= NLMSG_SPACE(0)) { nlh = (struct nlmsghdr *)skb->data; if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) - return 0; + goto out; rlen = NLMSG_ALIGN(nlh->nlmsg_len); if (rlen > skb->len) rlen = skb->len; @@ -58,9 +62,16 @@ static int event_recv_skb(struct sk_buff *skb) netlink_ack(skb, nlh, 0); skb_pull(skb, rlen); } + +out: +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) return 0; +#else + return; +#endif } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) static void event_recv(struct sock *sk, int length) { struct sk_buff *skb; @@ -72,6 +83,7 @@ static void event_recv(struct sock *sk, int length) kfree_skb(skb); } } +#endif static int notify(void *data, int len, int gfp_mask) { @@ -107,10 +119,16 @@ int event_send(u32 tid, u64 sid, u32 cid, u32 state, int atomic) int __init event_init(void) { #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)) - nl = netlink_kernel_create(NETLINK_ISCSI_SCST, 1, event_recv, THIS_MODULE); -#else - nl = netlink_kernel_create(NETLINK_ISCSI_SCST, 1, event_recv, NULL, + nl = netlink_kernel_create(NETLINK_ISCSI_SCST, 1, event_recv, THIS_MODULE); +#else + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + nl = netlink_kernel_create(NETLINK_ISCSI_SCST, 1, event_recv, NULL, + THIS_MODULE); + #else + nl = netlink_kernel_create(&init_net, NETLINK_ISCSI_SCST, 1, + event_recv_skb, NULL, THIS_MODULE); + #endif #endif if (!nl) { PRINT_ERROR("%s", "netlink_kernel_create() failed"); diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index 3a6f3d074..838922369 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -531,7 +531,7 @@ static void iscsi_set_datasize(struct iscsi_cmnd *cmnd, u32 offset, u32 size) if (cmnd->pdu.datasize & 3) { int idx = (offset + cmnd->pdu.datasize) >> PAGE_SHIFT; - u8 *p = (u8 *)page_address(cmnd->sg[idx].page) + + u8 *p = (u8 *)page_address(sg_page(&cmnd->sg[idx])) + ((offset + cmnd->pdu.datasize) & ~PAGE_MASK); int i = 4 - (cmnd->pdu.datasize & 3); while (i--) @@ -627,7 +627,7 @@ static struct iscsi_cmnd *create_status_rsp(struct iscsi_cmnd *req, int status, /* ToDo(); */ } rsp->own_sg = 1; - sense = (struct iscsi_sense_data *)page_address(sg[0].page); + sense = (struct iscsi_sense_data *)page_address(sg_page(&sg[0])); sense->length = cpu_to_be16(sense_len); memcpy(sense->data, sense_buf, sense_len); rsp->pdu.datasize = sizeof(struct iscsi_sense_data) + sense_len; @@ -686,7 +686,7 @@ static void iscsi_cmnd_reject(struct iscsi_cmnd *req, int reason) /* ToDo(); */ } rsp->own_sg = 1; - addr = page_address(sg[0].page); + addr = page_address(sg_page(&sg[0])); clear_page(addr); memcpy(addr, &req->pdu.bhs, sizeof(struct iscsi_hdr)); rsp->bufflen = rsp->pdu.datasize = sizeof(struct iscsi_hdr); @@ -817,6 +817,8 @@ static int cmnd_insert_hash(struct iscsi_cmnd *cmnd) TRACE_DBG("%p:%x", cmnd, itt); if (unlikely(itt == ISCSI_RESERVED_TAG)) { PRINT_ERROR("%s", "ITT is RESERVED_TAG"); + PRINT_BUFFER("Incorrect BHS", &cmnd->pdu.bhs, + sizeof(cmnd->pdu.bhs)); err = -ISCSI_REASON_PROTOCOL_ERROR; goto out; } @@ -894,7 +896,7 @@ static void cmnd_prepare_skip_pdu(struct iscsi_cmnd *cmnd) cmnd->bufflen = PAGE_SIZE; } - addr = page_address(sg[0].page); + addr = page_address(sg_page(&sg[0])); sBUG_ON(addr == NULL); size = (size + 3) & -4; conn->read_size = size; @@ -975,8 +977,7 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn, i = 0; while (1) { - sBUG_ON(sg[idx].page == NULL); - addr = page_address(sg[idx].page); + addr = page_address(sg_page(&sg[idx])); sBUG_ON(addr == NULL); conn->read_iov[i].iov_base = addr + offset; if (offset + size <= PAGE_SIZE) { @@ -1162,7 +1163,7 @@ static int noop_out_start(struct iscsi_cmnd *cmnd) for (i = 0; i < cmnd->sg_cnt; i++) { conn->read_iov[i].iov_base = - page_address(sg[i].page); + page_address(sg_page(&sg[i])); tmp = min_t(u32, size, PAGE_SIZE); conn->read_iov[i].iov_len = tmp; conn->read_size += tmp; diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 2cc9547eb..c32cebc66 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -96,17 +96,18 @@ again: if (cmnd_get_check(cmnd)) continue; for(i = 0; i < sg_cnt; i++) { - TRACE_CONN_CLOSE_DBG("page %p, net_priv %p, _count %d", - cmnd->sg[i].page, cmnd->sg[i].page->net_priv, - atomic_read(&cmnd->sg[i].page->_count)); + struct page *page = sg_page(&cmnd->sg[i]); + TRACE_CONN_CLOSE_DBG("page %p, net_priv %p, " + "_count %d", page, page->net_priv, + atomic_read(&page->_count)); - if (cmnd->sg[i].page->net_priv != NULL) { + if (page->net_priv != NULL) { if (restart == 0) { spin_unlock_bh(&conn->cmd_list_lock); restart = 1; } - while(cmnd->sg[i].page->net_priv != NULL) - iscsi_put_page_callback(cmnd->sg[i].page); + while(page->net_priv != NULL) + iscsi_put_page_callback(page); } } cmnd_put(cmnd); @@ -131,19 +132,19 @@ again: if (cmnd_get_check(rsp)) continue; for(i = 0; i < sg_cnt; i++) { + struct page *page = sg_page(&rsp->sg[i]); TRACE_CONN_CLOSE_DBG(" page %p, net_priv %p, " - "_count %d", rsp->sg[i].page, - rsp->sg[i].page->net_priv, - atomic_read(&rsp->sg[i].page->_count)); + "_count %d", page, page->net_priv, + atomic_read(&page->_count)); - if (rsp->sg[i].page->net_priv != NULL) { + if (page->net_priv != NULL) { if (restart == 0) { spin_unlock_bh(&cmnd->rsp_cmd_lock); spin_unlock_bh(&conn->cmd_list_lock); restart = 1; } - while(rsp->sg[i].page->net_priv != NULL) - iscsi_put_page_callback(rsp->sg[i].page); + while(page->net_priv != NULL) + iscsi_put_page_callback(page); } } cmnd_put(rsp); @@ -336,9 +337,10 @@ static void close_conn(struct iscsi_conn *conn) sg_cnt = get_pgcnt(cmnd->bufflen, cmnd->sg[0].offset); for(i = 0; i < sg_cnt; i++) { + struct page *page = sg_page(&cmnd->sg[i]); TRACE_CONN_CLOSE_DBG("page %p, net_priv %p, _count %d", - cmnd->sg[i].page, cmnd->sg[i].page->net_priv, - atomic_read(&cmnd->sg[i].page->_count)); + page, page->net_priv, + atomic_read(&page->_count)); } } @@ -356,9 +358,9 @@ static void close_conn(struct iscsi_conn *conn) sBUG_ON(rsp->sg_cnt != sg_cnt); for(i = 0; i < sg_cnt; i++) { TRACE_CONN_CLOSE_DBG(" page %p, net_priv %p, " - "_count %d", rsp->sg[i].page, - rsp->sg[i].page->net_priv, - atomic_read(&rsp->sg[i].page->_count)); + "_count %d", sg_page(&rsp->sg[i]), + sg_page(&rsp->sg[i])->net_priv, + atomic_read(&sg_page(&rsp->sg[i])->_count)); } } } @@ -809,8 +811,8 @@ void iscsi_put_page_callback(struct page *page) if (atomic_dec_and_test(&cmd->net_ref_cnt)) { int i, sg_cnt = get_pgcnt(cmd->bufflen, cmd->sg[0].offset); for(i = 0; i < sg_cnt; i++) { - TRACE_NET_PAGE("Clearing page %p", cmd->sg[i].page); - cmd->sg[i].page->net_priv = NULL; + TRACE_NET_PAGE("Clearing page %p", sg_page(&cmd->sg[i])); + sg_page(&cmd->sg[i])->net_priv = NULL; } cmnd_put(cmd); } @@ -923,31 +925,31 @@ retry: while (1) { #ifdef NET_PAGE_CALLBACKS_DEFINED - if (unlikely((sg[idx].page->net_priv != NULL) && - (sg[idx].page->net_priv != ref_cmd))) { + if (unlikely((sg_page(&sg[idx])->net_priv != NULL) && + (sg_page(&sg[idx])->net_priv != ref_cmd))) { PRINT_ERROR("net_priv isn't NULL and != ref_cmd " "(write_cmnd %p, ref_cmd %p, sg %p, idx %d, " "net_priv %p)", write_cmnd, ref_cmd, sg, idx, - sg[idx].page->net_priv); + sg_page(&sg[idx])->net_priv); sBUG(); } - sg[idx].page->net_priv = ref_cmd; + sg_page(&sg[idx])->net_priv = ref_cmd; #endif sendsize = PAGE_SIZE - offset; if (size <= sendsize) { retry2: - res = sendpage(sock, sg[idx].page, offset, size, flags); + res = sendpage(sock, sg_page(&sg[idx]), offset, size, flags); TRACE_WRITE("%s %#Lx:%u: %d(%lu,%u,%u)", sock->ops->sendpage ? "sendpage" : "sock_no_sendpage", (unsigned long long)conn->session->sid, conn->cid, - res, sg[idx].page->index, offset, size); + res, sg_page(&sg[idx])->index, offset, size); if (unlikely(res <= 0)) { if (res == -EINTR) goto retry2; else goto out_res; } - check_net_priv(ref_cmd, sg[idx].page); + check_net_priv(ref_cmd, sg_page(&sg[idx])); if (res == size) { conn->write_size = 0; return saved_size; @@ -958,19 +960,19 @@ retry2: } retry1: - res = sendpage(sock, sg[idx].page, offset, sendsize, + res = sendpage(sock, sg_page(&sg[idx]), offset, sendsize, flags | MSG_MORE); TRACE_WRITE("%s %#Lx:%u: %d(%lu,%u,%u)", sock->ops->sendpage ? "sendpage" : "sock_no_sendpage", (unsigned long long ) conn->session->sid, conn->cid, - res, sg[idx].page->index, offset, sendsize); + res, sg_page(&sg[idx])->index, offset, sendsize); if (unlikely(res <= 0)) { if (res == -EINTR) goto retry1; else goto out_res; } - check_net_priv(ref_cmd, sg[idx].page); + check_net_priv(ref_cmd, sg_page(&sg[idx])); if (res == sendsize) { idx++; offset = 0; @@ -988,7 +990,7 @@ out_iov: return saved_size - size; out_res: - check_net_priv(ref_cmd, sg[idx].page); + check_net_priv(ref_cmd, sg_page(&sg[idx])); if (res == -EAGAIN) goto out; /* else go through */ diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index 4fa5a9466..d43f812d0 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -1016,8 +1016,8 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, case CTIO_TIMEOUT: case CTIO_INVALID_RX_ID: /* they are OK */ - TRACE_MGMT_DBG("qla2x00tgt(%ld): CTIO with status %#x " - "received (LIP_RESET=e, ABORTED=2, " + TRACE(TRACE_MGMT_MINOR, "qla2x00tgt(%ld): CTIO with " + "status %#x received (LIP_RESET=e, ABORTED=2, " "TARGET_RESET=17, TIMEOUT=b, " "INVALID_RX_ID=8)", ha->instance, status); break; @@ -1052,7 +1052,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, goto out; } if (unlikely(err)) { - PRINT_INFO("Found by handle failed CTIO scst_cmd " + TRACE_MGMT_DBG("Found by handle failed CTIO scst_cmd " "%p (op %x)", scst_cmd, scst_cmd->cdb[0]); } } else if (ctio != NULL) { @@ -1075,7 +1075,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, goto out; } if (unlikely(err)) { - PRINT_INFO("Found by ctio failed CTIO scst_cmd %p " + TRACE_MGMT_DBG("Found by ctio failed CTIO scst_cmd %p " "(op %x)", scst_cmd, scst_cmd->cdb[0]); } @@ -1085,7 +1085,8 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd); if (unlikely(err)) { - PRINT_INFO("Failed CTIO state %d", cmd->state); + TRACE(TRACE_MGMT_MINOR, "Failed CTIO state %d (err %x)", + cmd->state, status); } if (cmd->state == Q2T_STATE_PROCESSED) { @@ -1120,7 +1121,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, scst_rx_data(scst_cmd, rx_status, context); } else if (cmd->state == Q2T_STATE_ABORTED) { - TRACE_DBG("Aborted command %p finished", cmd); + TRACE_MGMT_DBG("Aborted command %p finished", cmd); goto out_free; } else { PRINT_ERROR("qla2x00tgt(%ld): A command in state (%d) should " diff --git a/qla2x00t/qla2x00-target/qla2x00t.h b/qla2x00t/qla2x00-target/qla2x00t.h index 3dc7ba0c7..cfcea70a7 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.h +++ b/qla2x00t/qla2x00-target/qla2x00t.h @@ -69,10 +69,10 @@ #define NOTIFY_ACK_TM_RESP_CODE_VALID BIT_4 /* Command's states */ -#define Q2T_STATE_NEW 0 /* New command and SCST processes it */ +#define Q2T_STATE_NEW 0 /* New command and SCST processing it */ #define Q2T_STATE_PROCESSED 1 /* SCST done processing */ -#define Q2T_STATE_NEED_DATA 2 /* SCST needs data to process */ -#define Q2T_STATE_DATA_IN 3 /* Data arrived and SCST processes it */ +#define Q2T_STATE_NEED_DATA 2 /* SCST needs data to continue */ +#define Q2T_STATE_DATA_IN 3 /* Data arrived and SCST processing them */ #define Q2T_STATE_ABORTED 4 /* Command aborted */ /* Misc */ diff --git a/qla2x00t/qla_attr.c b/qla2x00t/qla_attr.c index f22a958c2..c2edd9c28 100644 --- a/qla2x00t/qla_attr.c +++ b/qla2x00t/qla_attr.c @@ -61,14 +61,14 @@ qla2x00_store_tgt_enabled(struct class_device *cdev, case '0' : if ((ha->flags.enable_target_mode) || force) { qla_target.tgt_host_action(ha, DISABLE_TARGET_MODE); + msleep_interruptible(10*1000); } - msleep_interruptible(3*1000); break; case '1' : if ((ha->flags.enable_target_mode == 0) || force) { qla_target.tgt_host_action(ha, ENABLE_TARGET_MODE); + msleep_interruptible(10*1000); } - msleep_interruptible(3*1000); break; default: printk("%s: Requested action not understood: %s\n", diff --git a/scst/include/scsi_tgt.h b/scst/include/scsi_tgt.h index 91ded86f0..437986837 100644 --- a/scst/include/scsi_tgt.h +++ b/scst/include/scsi_tgt.h @@ -36,6 +36,10 @@ #include +#ifndef DECLARE_MUTEX_LOCKED +#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0) +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) typedef _Bool bool; #endif @@ -2235,6 +2239,52 @@ static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd) return mcmd->status; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + +static inline struct page *sg_page(struct scatterlist *sg) +{ + return sg->page; +} + +static inline void *sg_virt(struct scatterlist *sg) +{ + return page_address(sg_page(sg)) + sg->offset; +} + +static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) +{ + memset(sgl, 0, sizeof(*sgl) * nents); +} + +static inline void sg_assign_page(struct scatterlist *sg, struct page *page) +{ + sg->page = page; +} + +static inline void sg_set_page(struct scatterlist *sg, struct page *page, + unsigned int len, unsigned int offset) +{ + sg_assign_page(sg, page); + sg->offset = offset; + sg->length = len; +} + +static inline void sg_set_buf(struct scatterlist *sg, const void *buf, + unsigned int buflen) +{ + sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); +} + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) */ + +static inline void sg_clear(struct scatterlist *sg) +{ + memset(sg, 0, sizeof(*sg)); +#ifdef CONFIG_DEBUG_SG + sg->sg_magic = SG_MAGIC; +#endif +} + /* * Functions for access to the commands data (SG) buffer, * including HIGHMEM environment. Should be used instead of direct @@ -2245,7 +2295,41 @@ static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd) * * The "put" function unmaps the buffer. */ -int __scst_get_buf(struct scst_cmd *cmd, uint8_t **buf); +static inline int __scst_get_buf(struct scst_cmd *cmd, uint8_t **buf) +{ + int res = 0; + struct scatterlist *sg = cmd->sg; + int i = cmd->get_sg_buf_entry_num; + + *buf = NULL; + + if ((i >= cmd->sg_cnt) || unlikely(sg == NULL)) + goto out; +#ifdef SCST_HIGHMEM /* HIGHMEM isn't currently supported */ + /* + * HIGHMEM pages not merged (clustered), so if it's + * not HIGHMEM page, kmap() is the same as page_address() + */ + if (scst_cmd_atomic(cmd)) { + enum km_type km; + if (in_softirq()) + km = KM_SOFTIRQ0; + else + km = KM_USER0; + *buf = kmap_atomic(sg[i].page, km); + } else + *buf = kmap(sg[i].page); +#else + *buf = page_address(sg_page(&sg[i])); +#endif + *buf += sg[i].offset; + res = sg[i].length; + cmd->get_sg_buf_entry_num++; + +out: + return res; +} + static inline int scst_get_buf_first(struct scst_cmd *cmd, uint8_t **buf) { cmd->get_sg_buf_entry_num = 0; @@ -2260,7 +2344,7 @@ static inline int scst_get_buf_next(struct scst_cmd *cmd, uint8_t **buf) static inline void scst_put_buf(struct scst_cmd *cmd, void *buf) { -#ifdef SCST_HIGHMEM +#ifdef SCST_HIGHMEM /* HIGHMEM isn't currently supported */ if (cmd->sg_cnt) { if (scst_cmd_atomic(cmd)) { enum km_type km; diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index 1ab385f3d..ea724fadd 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -346,17 +346,16 @@ static struct page *dev_user_alloc_pages(struct scatterlist *sg, if (ucmd->cur_data_page >= ucmd->num_data_pages) goto out; - sg->page = ucmd->data_pages[ucmd->cur_data_page]; - sg->length = PAGE_SIZE - sg->offset; - + sg_set_page(sg, ucmd->data_pages[ucmd->cur_data_page], + PAGE_SIZE - sg->offset, 0); ucmd->cur_data_page++; - TRACE_MEM("page=%p, length=%d", sg->page, sg->length); - TRACE_BUFFER("Page data", page_address(sg->page), sg->length); + TRACE_MEM("page=%p, length=%d", sg_page(sg), sg->length); + TRACE_BUFFER("Page data", sg_virt(sg), sg->length); out: TRACE_EXIT(); - return sg->page; + return sg_page(sg); } static void dev_user_on_cached_mem_free(struct scst_user_cmd *ucmd) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index cb18b3340..935d9d97a 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -2196,12 +2196,18 @@ static inline void blockio_check_finish(struct blockio_work *blockio_work) } } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) static int blockio_endio(struct bio *bio, unsigned int bytes_done, int error) +#else +static void blockio_endio(struct bio *bio, int error) +#endif { struct blockio_work *blockio_work = bio->bi_private; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) if (bio->bi_size) return 1; +#endif error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO; @@ -2224,7 +2230,11 @@ static int blockio_endio(struct bio *bio, unsigned int bytes_done, int error) blockio_check_finish(blockio_work); bio_put(bio); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) return 0; +#else + return; +#endif } static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr, @@ -2233,10 +2243,10 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr, struct scst_vdisk_dev *virt_dev = thr->virt_dev; struct block_device *bdev = thr->bdev; struct request_queue *q = bdev_get_queue(bdev); - int j, max_nr_vecs = 0; + int length, max_nr_vecs = 0; + uint8_t *address; struct bio *bio = NULL, *hbio = NULL, *tbio = NULL; int need_new_bio; - struct scatterlist *sgl = cmd->sg; struct blockio_work *blockio_work; int bios = 0; @@ -2258,24 +2268,27 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr, max_nr_vecs = 1; need_new_bio = 1; - for (j = 0; j < cmd->sg_cnt; ++j) { - int len, bytes, off, thislen; - struct page *page; - page = sgl[j].page; - off = sgl[j].offset; - len = sgl[j].length; + length = scst_get_buf_first(cmd, &address); + while(length > 0) { + int len, bytes, off, thislen; + uint8_t *addr; + + addr = address; + off = offset_in_page(addr); + len = length; thislen = 0; while (len > 0) { int rc; + struct page *page = virt_to_page(addr); if (need_new_bio) { bio = bio_alloc(GFP_KERNEL, max_nr_vecs); if (!bio) { PRINT_ERROR("Failed to create bio " - "for data segment= %d " - "cmd %p", j, cmd); + "for data segment= %d cmd %p", + cmd->get_sg_buf_entry_num, cmd); goto out_no_bio; } @@ -2306,13 +2319,16 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr, continue; } - page++; + addr += PAGE_SIZE; thislen += bytes; len -= bytes; off = 0; } - lba_start += sgl[j].length >> virt_dev->block_shift; + lba_start += length >> virt_dev->block_shift; + + scst_put_buf(cmd, address); + length = scst_get_buf_next(cmd, &address); } /* +1 to prevent erroneous too early command completion */ diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 53ad83528..5f8725e5a 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -1567,44 +1567,6 @@ out: return; } -int __scst_get_buf(struct scst_cmd *cmd, uint8_t **buf) -{ - int res = 0; - struct scatterlist *sg = cmd->sg; - int i = cmd->get_sg_buf_entry_num; - - TRACE_ENTRY(); - - *buf = NULL; - - if ((i >= cmd->sg_cnt) || unlikely(sg == NULL)) - goto out; -#ifdef SCST_HIGHMEM - /* - * HIGHMEM pages not merged (clustered), so if it's - * not HIGHMEM page, kmap() is the same as page_address() - */ - if (scst_cmd_atomic(cmd)) { - enum km_type km; - if (in_softirq()) - km = KM_SOFTIRQ0; - else - km = KM_USER0; - *buf = kmap_atomic(sg[i].page, km); - } else - *buf = kmap(sg[i].page); -#else - *buf = page_address(sg[i].page); -#endif - *buf += sg[i].offset; - res = sg[i].length; - cmd->get_sg_buf_entry_num++; - -out: - TRACE_EXIT_RES(res); - return res; -} - static const int SCST_CDB_LENGTH[8] = { 6, 10, 10, -1, 16, 12, -1, -1 }; #define SCST_CDB_GROUP(opcode) ((opcode >> 5) & 0x7) diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 9365d02a0..0fe5be7c0 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -296,7 +296,7 @@ struct scst_tgt *scst_register(struct scst_tgt_template *vtt, tgt = kzalloc(sizeof(*tgt), GFP_KERNEL); if (tgt == NULL) { - TRACE(TRACE_OUT_OF_MEM, "%s", "kzalloc() failed"); + TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of tgt failed"); goto out_err; } @@ -1736,7 +1736,6 @@ EXPORT_SYMBOL(scst_proc_log_entry_write); EXPORT_SYMBOL(scst_create_proc_entry); EXPORT_SYMBOL(scst_single_seq_open); -EXPORT_SYMBOL(__scst_get_buf); EXPORT_SYMBOL(scst_get); EXPORT_SYMBOL(scst_put); diff --git a/scst/src/scst_mem.c b/scst/src/scst_mem.c index 88d869e00..9cb04c2d2 100644 --- a/scst/src/scst_mem.c +++ b/scst/src/scst_mem.c @@ -75,7 +75,7 @@ static int scst_check_clustering(struct scatterlist *sg, int cur, int hint) { int res = -1; int i = hint; - unsigned long pfn_cur = page_to_pfn(sg[cur].page); + unsigned long pfn_cur = page_to_pfn(sg_page(&sg[cur])); int len_cur = sg[cur].length; unsigned long pfn_cur_next = pfn_cur + (len_cur >> PAGE_SHIFT); int full_page_cur = (len_cur & (PAGE_SIZE - 1)) == 0; @@ -95,7 +95,7 @@ static int scst_check_clustering(struct scatterlist *sg, int cur, int hint) /* check the hint first */ if (i >= 0) { - pfn = page_to_pfn(sg[i].page); + pfn = page_to_pfn(sg_page(&sg[i])); pfn_next = pfn + (sg[i].length >> PAGE_SHIFT); full_page = (sg[i].length & (PAGE_SIZE - 1)) == 0; @@ -108,7 +108,7 @@ static int scst_check_clustering(struct scatterlist *sg, int cur, int hint) /* ToDo: implement more intelligent search */ for(i = cur - 1; i >= 0; i--) { - pfn = page_to_pfn(sg[i].page); + pfn = page_to_pfn(sg_page(&sg[i])); pfn_next = pfn + (sg[i].length >> PAGE_SHIFT); full_page = (sg[i].length & (PAGE_SIZE - 1)) == 0; @@ -125,15 +125,15 @@ out: out_tail: TRACE_MEM("SG segment %d will be tail merged with segment %d", cur, i); sg[i].length += len_cur; - memset(&sg[cur], 0, sizeof(sg[cur])); + sg_clear(&sg[cur]); res = i; goto out; out_head: TRACE_MEM("SG segment %d will be head merged with segment %d", cur, i); - sg[i].page = sg[cur].page; + sg_assign_page(&sg[i], sg_page(&sg[cur])); sg[i].length += len_cur; - memset(&sg[cur], 0, sizeof(sg[cur])); + sg_clear(&sg[cur]); res = i; goto out; } @@ -146,7 +146,7 @@ static void scst_free_sys_sg_entries(struct scatterlist *sg, int sg_count, TRACE_MEM("sg=%p, sg_count=%d", sg, sg_count); for(i = 0; i < sg_count; i++) { - struct page *p = sg[i].page; + struct page *p = sg_page(&sg[i]); int len = sg[i].length; int pages = (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0); @@ -182,15 +182,15 @@ static void scst_free_sys_sg_entries(struct scatterlist *sg, int sg_count, static struct page *scst_alloc_sys_pages(struct scatterlist *sg, gfp_t gfp_mask, void *priv) { - sg->page = alloc_pages(gfp_mask, 0); - sg->offset = 0; - sg->length = PAGE_SIZE; - TRACE_MEM("page=%p, sg=%p, priv=%p", sg->page, sg, priv); - if (sg->page == NULL) { + struct page *page = alloc_pages(gfp_mask, 0); + + sg_set_page(sg, page, PAGE_SIZE, 0); + TRACE_MEM("page=%p, sg=%p, priv=%p", page, sg, priv); + if (page == NULL) { TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of " "sg page failed"); } - return sg->page; + return page; } static int scst_alloc_sg_entries(struct scatterlist *sg, int pages, @@ -265,7 +265,7 @@ static int sgv_alloc_arrays(struct sgv_pool_obj *obj, sz = pages_to_alloc * sizeof(obj->sg_entries[0]); - obj->sg_entries = (struct scatterlist*)kzalloc(sz, gfp_mask); + obj->sg_entries = (struct scatterlist*)kmalloc(sz, gfp_mask); if (unlikely(obj->sg_entries == NULL)) { TRACE(TRACE_OUT_OF_MEM, "Allocation of sgv_pool_obj " "SG vector failed (size %d)", sz); @@ -273,6 +273,8 @@ static int sgv_alloc_arrays(struct sgv_pool_obj *obj, goto out; } + sg_init_table(obj->sg_entries, pages_to_alloc); + if (obj->owner_pool->clustered) { if (order <= sgv_pools_mgr.sgv_max_trans_order) { obj->trans_tbl = (struct trans_tbl_ent*)obj->sg_entries_data; @@ -528,7 +530,6 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size, if (obj->sg_count != 0) { TRACE_MEM("Cached sgv_obj %p", obj); EXTRACHECKS_BUG_ON(obj->order != order); - atomic_inc(&pool->acc.hit_alloc); atomic_inc(&pool->cache_acc[order].hit_alloc); goto success; } @@ -540,9 +541,8 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size, TRACE_MEM("Brand new sgv_obj %p", obj); if (order <= sgv_pools_mgr.sgv_max_local_order) { obj->sg_entries = obj->sg_entries_data; + sg_init_table(obj->sg_entries, pages_to_alloc); TRACE_MEM("sg_entries %p", obj->sg_entries); - memset(obj->sg_entries, 0, - pages_to_alloc*sizeof(obj->sg_entries[0])); if (pool->clustered) { obj->trans_tbl = (struct trans_tbl_ent*) (obj->sg_entries + pages_to_alloc); @@ -572,16 +572,19 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size, goto out_return2; cache = NULL; sz = sizeof(*obj) + pages*sizeof(obj->sg_entries[0]); - obj = kzalloc(sz, gfp_mask); + obj = kmalloc(sz, gfp_mask); if (unlikely(obj == NULL)) { TRACE(TRACE_OUT_OF_MEM, "Allocation of " "sgv_pool_obj failed (size %d)", size); goto out_fail; } + memset(obj, 0, sizeof(*obj)); obj->owner_pool = pool; obj->order = -1 - order; - obj->sg_entries = obj->sg_entries_data; obj->allocator_priv = priv; + + obj->sg_entries = obj->sg_entries_data; + sg_init_table(obj->sg_entries, pages); if (sgv_pool_hiwmk_check(pages_to_alloc, no_fail) != 0) goto out_fail_free_sg_entries; @@ -600,7 +603,6 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size, } success: - atomic_inc(&pool->acc.total_alloc); spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); sgv_pools_mgr.mgr.thr.active_pages_total += 1 << order; spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); @@ -728,10 +730,12 @@ struct scatterlist *scst_alloc(int size, unsigned long gfp_mask, int *count) goto out; } - res = kzalloc(pages*sizeof(*res), gfp_mask); + res = kmalloc(pages*sizeof(*res), gfp_mask); if (res == NULL) goto out; + sg_init_table(res, pages); + /* * If we allow use clustering here, we will have troubles in * scst_free() to figure out how many pages are in the SG vector. @@ -791,8 +795,6 @@ int sgv_pool_init(struct sgv_pool *pool, const char *name, int clustered) atomic_set(&pool->acc.other_alloc, 0); atomic_set(&pool->acc.big_alloc, 0); - atomic_set(&pool->acc.total_alloc, 0); - atomic_set(&pool->acc.hit_alloc, 0); pool->clustered = clustered; pool->alloc_fns.alloc_pages_fn = scst_alloc_sys_pages; @@ -1058,8 +1060,8 @@ int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark) int res; struct scst_sgv_pools_manager *pools = &sgv_pools_mgr; - TRACE_ENTRY(); + memset(pools, 0, sizeof(*pools)); sgv_pools_mgr.mgr.thr.hi_wmk = mem_hwmark >> PAGE_SHIFT; @@ -1154,11 +1156,15 @@ void scst_sgv_pools_deinit(void) static void scst_do_sgv_read(struct seq_file *seq, const struct sgv_pool *pool) { - int i; + int i, total = 0, hit = 0; + + for(i = 0; i < SGV_POOL_ELEMENTS; i++) { + hit += atomic_read(&pool->cache_acc[i].hit_alloc); + total += atomic_read(&pool->cache_acc[i].total_alloc); + } seq_printf(seq, "\n%-30s %-11d %-11d %d/%d (P/O)\n", pool->name, - atomic_read(&pool->acc.hit_alloc), - atomic_read(&pool->acc.total_alloc), + hit, total, pool->acc.cached_pages, pool->acc.cached_entries); diff --git a/scst/src/scst_mem.h b/scst/src/scst_mem.h index e1da64649..42a426893 100644 --- a/scst/src/scst_mem.h +++ b/scst/src/scst_mem.h @@ -52,7 +52,6 @@ struct sgv_pool_obj struct sgv_pool_acc { - atomic_t total_alloc, hit_alloc; u32 cached_pages, cached_entries; atomic_t big_alloc, other_alloc; }; diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 772fa7f22..5f3fccc18 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -1211,10 +1211,10 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state) int i; struct scatterlist *sg = cmd->sg; TRACE_RECV_TOP("Exec'd %d S/G(s) at %p sg[0].page at " - "%p", cmd->sg_cnt, sg, (void*)sg[0].page); + "%p", cmd->sg_cnt, sg, (void*)sg_page(&sg[0])); for(i = 0; i < cmd->sg_cnt; ++i) { TRACE_BUFF_FLAG(TRACE_RCV_TOP, - "Exec'd sg", page_address(sg[i].page), + "Exec'd sg", sg_virt(&sg[i]), sg[i].length); } } @@ -2553,10 +2553,10 @@ static int scst_xmit_response(struct scst_cmd *cmd) int i; struct scatterlist *sg = cmd->sg; TRACE_SEND_BOT("Xmitting %d S/G(s) at %p sg[0].page at %p", - cmd->sg_cnt, sg, (void*)sg[0].page); + cmd->sg_cnt, sg, (void*)sg_page(&sg[0])); for(i = 0; i < cmd->sg_cnt; ++i) { TRACE_BUFF_FLAG(TRACE_SND_BOT, - "Xmitting sg", page_address(sg[i].page), + "Xmitting sg", sg_virt(&sg[i]), sg[i].length); } }