亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? iscsi_tcp.c

?? linux 內核源代碼
?? C
?? 第 1 頁 / 共 5 頁
字號:
/* * iSCSI Initiator over TCP/IP Data-Path * * Copyright (C) 2004 Dmitry Yusupov * Copyright (C) 2004 Alex Aizman * Copyright (C) 2005 - 2006 Mike Christie * Copyright (C) 2006 Red Hat, Inc.  All rights reserved. * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * See the file COPYING included with this distribution for more details. * * Credits: *	Christoph Hellwig *	FUJITA Tomonori *	Arne Redlich *	Zhenyu Wang */#include <linux/types.h>#include <linux/list.h>#include <linux/inet.h>#include <linux/file.h>#include <linux/blkdev.h>#include <linux/crypto.h>#include <linux/delay.h>#include <linux/kfifo.h>#include <linux/scatterlist.h>#include <net/tcp.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_device.h>#include <scsi/scsi_host.h>#include <scsi/scsi.h>#include <scsi/scsi_transport_iscsi.h>#include "iscsi_tcp.h"MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, "	      "Alex Aizman <itn780@yahoo.com>");MODULE_DESCRIPTION("iSCSI/TCP data-path");MODULE_LICENSE("GPL");/* #define DEBUG_TCP */#define DEBUG_ASSERT#ifdef DEBUG_TCP#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt)#else#define debug_tcp(fmt...)#endif#ifndef DEBUG_ASSERT#ifdef BUG_ON#undef BUG_ON#endif#define BUG_ON(expr)#endifstatic unsigned int iscsi_max_lun = 512;module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);static inline voidiscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size){	sg_init_one(&ibuf->sg, vbuf, size);	ibuf->sent = 0;	ibuf->use_sendmsg = 1;}static inline voidiscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg){	sg_init_table(&ibuf->sg, 1);	sg_set_page(&ibuf->sg, sg_page(sg), sg->length, sg->offset);	/*	 * Fastpath: sg element fits into single page	 */	if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg_page(sg)))		ibuf->use_sendmsg = 0;	else		ibuf->use_sendmsg = 1;	ibuf->sent = 0;}static inline intiscsi_buf_left(struct iscsi_buf *ibuf){	int rc;	rc = ibuf->sg.length - ibuf->sent;	BUG_ON(rc < 0);	return rc;}static inline voidiscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf,		 u8* crc){	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;	crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);	buf->sg.length += sizeof(u32);}static inline intiscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn){	struct sk_buff *skb = tcp_conn->in.skb;	tcp_conn->in.zero_copy_hdr = 0;	if (tcp_conn->in.copy >= tcp_conn->hdr_size &&	    tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER) {		/*		 * Zero-copy PDU Header: using connection context		 * to store header pointer.		 */		if (skb_shinfo(skb)->frag_list == NULL &&		    !skb_shinfo(skb)->nr_frags) {			tcp_conn->in.hdr = (struct iscsi_hdr *)				((char*)skb->data + tcp_conn->in.offset);			tcp_conn->in.zero_copy_hdr = 1;		} else {			/* ignoring return code since we checked			 * in.copy before */			skb_copy_bits(skb, tcp_conn->in.offset,				&tcp_conn->hdr, tcp_conn->hdr_size);			tcp_conn->in.hdr = &tcp_conn->hdr;		}		tcp_conn->in.offset += tcp_conn->hdr_size;		tcp_conn->in.copy -= tcp_conn->hdr_size;	} else {		int hdr_remains;		int copylen;		/*		 * PDU header scattered across SKB's,		 * copying it... This'll happen quite rarely.		 */		if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER)			tcp_conn->in.hdr_offset = 0;		hdr_remains = tcp_conn->hdr_size - tcp_conn->in.hdr_offset;		BUG_ON(hdr_remains <= 0);		copylen = min(tcp_conn->in.copy, hdr_remains);		skb_copy_bits(skb, tcp_conn->in.offset,			(char*)&tcp_conn->hdr + tcp_conn->in.hdr_offset,			copylen);		debug_tcp("PDU gather offset %d bytes %d in.offset %d "		       "in.copy %d\n", tcp_conn->in.hdr_offset, copylen,		       tcp_conn->in.offset, tcp_conn->in.copy);		tcp_conn->in.offset += copylen;		tcp_conn->in.copy -= copylen;		if (copylen < hdr_remains)  {			tcp_conn->in_progress = IN_PROGRESS_HEADER_GATHER;			tcp_conn->in.hdr_offset += copylen;		        return -EAGAIN;		}		tcp_conn->in.hdr = &tcp_conn->hdr;		tcp_conn->discontiguous_hdr_cnt++;	        tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;	}	return 0;}/* * must be called with session lock */static voidiscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask){	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;	struct iscsi_r2t_info *r2t;	struct scsi_cmnd *sc;	/* flush ctask's r2t queues */	while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,			    sizeof(void*));		debug_scsi("iscsi_tcp_cleanup_ctask pending r2t dropped\n");	}	sc = ctask->sc;	if (unlikely(!sc))		return;	tcp_ctask->xmstate = XMSTATE_VALUE_IDLE;	tcp_ctask->r2t = NULL;}/** * iscsi_data_rsp - SCSI Data-In Response processing * @conn: iscsi connection * @ctask: scsi command task **/static intiscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask){	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;	struct iscsi_session *session = conn->session;	struct scsi_cmnd *sc = ctask->sc;	int datasn = be32_to_cpu(rhdr->datasn);	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);	/*	 * setup Data-In byte counter (gets decremented..)	 */	ctask->data_count = tcp_conn->in.datalen;	if (tcp_conn->in.datalen == 0)		return 0;	if (tcp_ctask->exp_datasn != datasn) {		debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->datasn(%d)\n",		          __FUNCTION__, tcp_ctask->exp_datasn, datasn);		return ISCSI_ERR_DATASN;	}	tcp_ctask->exp_datasn++;	tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);	if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {		debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",		          __FUNCTION__, tcp_ctask->data_offset,		          tcp_conn->in.datalen, scsi_bufflen(sc));		return ISCSI_ERR_DATA_OFFSET;	}	if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {		conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;		if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {			int res_count = be32_to_cpu(rhdr->residual_count);			if (res_count > 0 &&			    res_count <= scsi_bufflen(sc)) {				scsi_set_resid(sc, res_count);				sc->result = (DID_OK << 16) | rhdr->cmd_status;			} else				sc->result = (DID_BAD_TARGET << 16) |					rhdr->cmd_status;		} else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) {			scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));			sc->result = (DID_OK << 16) | rhdr->cmd_status;		} else			sc->result = (DID_OK << 16) | rhdr->cmd_status;	}	conn->datain_pdus_cnt++;	return 0;}/** * iscsi_solicit_data_init - initialize first Data-Out * @conn: iscsi connection * @ctask: scsi command task * @r2t: R2T info * * Notes: *	Initialize first Data-Out within this R2T sequence and finds *	proper data_offset within this SCSI command. * *	This function is called with connection lock taken. **/static voidiscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,			struct iscsi_r2t_info *r2t){	struct iscsi_data *hdr;	struct scsi_cmnd *sc = ctask->sc;	int i, sg_count = 0;	struct scatterlist *sg;	hdr = &r2t->dtask.hdr;	memset(hdr, 0, sizeof(struct iscsi_data));	hdr->ttt = r2t->ttt;	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);	r2t->solicit_datasn++;	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));	hdr->itt = ctask->hdr->itt;	hdr->exp_statsn = r2t->exp_statsn;	hdr->offset = cpu_to_be32(r2t->data_offset);	if (r2t->data_length > conn->max_xmit_dlength) {		hton24(hdr->dlength, conn->max_xmit_dlength);		r2t->data_count = conn->max_xmit_dlength;		hdr->flags = 0;	} else {		hton24(hdr->dlength, r2t->data_length);		r2t->data_count = r2t->data_length;		hdr->flags = ISCSI_FLAG_CMD_FINAL;	}	conn->dataout_pdus_cnt++;	r2t->sent = 0;	iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,			   sizeof(struct iscsi_hdr));	sg = scsi_sglist(sc);	r2t->sg = NULL;	for (i = 0; i < scsi_sg_count(sc); i++, sg += 1) {		/* FIXME: prefetch ? */		if (sg_count + sg->length > r2t->data_offset) {			int page_offset;			/* sg page found! */			/* offset within this page */			page_offset = r2t->data_offset - sg_count;			/* fill in this buffer */			iscsi_buf_init_sg(&r2t->sendbuf, sg);			r2t->sendbuf.sg.offset += page_offset;			r2t->sendbuf.sg.length -= page_offset;			/* xmit logic will continue with next one */			r2t->sg = sg + 1;			break;		}		sg_count += sg->length;	}	BUG_ON(r2t->sg == NULL);}/** * iscsi_r2t_rsp - iSCSI R2T Response processing * @conn: iscsi connection * @ctask: scsi command task **/static intiscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask){	struct iscsi_r2t_info *r2t;	struct iscsi_session *session = conn->session;	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;	struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;	int r2tsn = be32_to_cpu(rhdr->r2tsn);	int rc;	if (tcp_conn->in.datalen) {		printk(KERN_ERR "iscsi_tcp: invalid R2t with datalen %d\n",		       tcp_conn->in.datalen);		return ISCSI_ERR_DATALEN;	}	if (tcp_ctask->exp_datasn != r2tsn){		debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->r2tsn(%d)\n",		          __FUNCTION__, tcp_ctask->exp_datasn, r2tsn);		return ISCSI_ERR_R2TSN;	}	/* fill-in new R2T associated with the task */	spin_lock(&session->lock);	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);	if (!ctask->sc || ctask->mtask ||	     session->state != ISCSI_STATE_LOGGED_IN) {		printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "		       "recovery...\n", ctask->itt);		spin_unlock(&session->lock);		return 0;	}	rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));	BUG_ON(!rc);	r2t->exp_statsn = rhdr->statsn;	r2t->data_length = be32_to_cpu(rhdr->data_length);	if (r2t->data_length == 0) {		printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n");		spin_unlock(&session->lock);		return ISCSI_ERR_DATALEN;	}	if (r2t->data_length > session->max_burst)		debug_scsi("invalid R2T with data len %u and max burst %u."			   "Attempting to execute request.\n",			    r2t->data_length, session->max_burst);	r2t->data_offset = be32_to_cpu(rhdr->data_offset);	if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {		spin_unlock(&session->lock);		printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "		       "offset %u and total length %d\n", r2t->data_length,		       r2t->data_offset, scsi_bufflen(ctask->sc));		return ISCSI_ERR_DATALEN;	}	r2t->ttt = rhdr->ttt; /* no flip */	r2t->solicit_datasn = 0;	iscsi_solicit_data_init(conn, ctask, r2t);	tcp_ctask->exp_datasn = r2tsn + 1;	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));	set_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate);	list_move_tail(&ctask->running, &conn->xmitqueue);	scsi_queue_work(session->host, &conn->xmitwork);	conn->r2t_pdus_cnt++;	spin_unlock(&session->lock);	return 0;}static intiscsi_tcp_hdr_recv(struct iscsi_conn *conn){	int rc = 0, opcode, ahslen;	struct iscsi_hdr *hdr;	struct iscsi_session *session = conn->session;	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;	uint32_t cdgst, rdgst = 0, itt;	hdr = tcp_conn->in.hdr;	/* verify PDU length */	tcp_conn->in.datalen = ntoh24(hdr->dlength);	if (tcp_conn->in.datalen > conn->max_recv_dlength) {		printk(KERN_ERR "iscsi_tcp: datalen %d > %d\n",		       tcp_conn->in.datalen, conn->max_recv_dlength);		return ISCSI_ERR_DATALEN;	}	tcp_conn->data_copied = 0;	/* read AHS */	ahslen = hdr->hlength << 2;	tcp_conn->in.offset += ahslen;	tcp_conn->in.copy -= ahslen;	if (tcp_conn->in.copy < 0) {		printk(KERN_ERR "iscsi_tcp: can't handle AHS with length "		       "%d bytes\n", ahslen);		return ISCSI_ERR_AHSLEN;	}	/* calculate read padding */	tcp_conn->in.padding = tcp_conn->in.datalen & (ISCSI_PAD_LEN-1);	if (tcp_conn->in.padding) {		tcp_conn->in.padding = ISCSI_PAD_LEN - tcp_conn->in.padding;		debug_scsi("read padding %d bytes\n", tcp_conn->in.padding);	}	if (conn->hdrdgst_en) {		struct scatterlist sg;		sg_init_one(&sg, (u8 *)hdr,			    sizeof(struct iscsi_hdr) + ahslen);		crypto_hash_digest(&tcp_conn->rx_hash, &sg, sg.length,

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产精品一区不卡| 青青草一区二区三区| wwwwxxxxx欧美| 日韩欧美三级在线| 欧美精品一区二区在线观看| 8x福利精品第一导航| 欧美一区2区视频在线观看| 欧美顶级少妇做爰| 日韩亚洲欧美中文三级| 欧美精品一区视频| 国产精品久久久久四虎| 亚洲欧美日韩国产综合在线 | 一区二区三区欧美激情| 亚洲欧美日韩电影| 亚洲小说欧美激情另类| 青青草伊人久久| 国产乱码精品一品二品| 99精品视频在线免费观看| 欧美综合天天夜夜久久| 911精品国产一区二区在线| 精品久久久网站| 自拍偷在线精品自拍偷无码专区| 亚洲色图.com| 美脚の诱脚舐め脚责91| 日韩午夜精品电影| 欧美中文字幕久久| 欧美绝品在线观看成人午夜影视| 91精品国产一区二区三区蜜臀| 日韩欧美国产小视频| 国产精品视频免费| 午夜精品免费在线| 国产成a人亚洲精品| 在线观看亚洲a| 久久久久久亚洲综合影院红桃| 亚洲同性同志一二三专区| 香蕉乱码成人久久天堂爱免费| 另类中文字幕网| 色婷婷综合久久久久中文| 555夜色666亚洲国产免| 中文字幕免费观看一区| 性感美女极品91精品| 成人黄色网址在线观看| 日韩亚洲欧美在线| 一区二区三区在线观看视频| 亚洲电影在线免费观看| 日韩高清在线电影| 欧洲视频一区二区| 国产午夜亚洲精品午夜鲁丝片 | 一区二区三区国产豹纹内裤在线| 日本午夜精品一区二区三区电影 | 欧美三级电影精品| 欧美国产欧美亚州国产日韩mv天天看完整 | 99精品视频在线免费观看| 欧美电视剧免费全集观看| 亚洲综合一区二区三区| 成人app在线观看| 久久久久久一二三区| 日本伊人色综合网| 宅男在线国产精品| 午夜国产不卡在线观看视频| 91在线国产观看| 国产精品区一区二区三区| 精品一区二区综合| 日韩三级精品电影久久久| 亚洲3atv精品一区二区三区| 在线中文字幕一区| 亚洲精品中文在线影院| 99精品热视频| 亚洲欧洲成人精品av97| 国产**成人网毛片九色| 久久美女高清视频| 国产激情一区二区三区桃花岛亚洲| 日韩精品中午字幕| 蜜臀av性久久久久蜜臀aⅴ四虎| 欧美日韩亚洲综合一区二区三区| 亚洲乱码中文字幕综合| 91一区二区三区在线观看| 亚洲欧美综合在线精品| 一本大道久久a久久综合| 亚洲三级在线观看| 欧美日韩亚洲国产综合| 青娱乐精品视频在线| 日韩美女一区二区三区| 狠狠色丁香婷婷综合| 久久久99精品免费观看不卡| 成人在线一区二区三区| 国产精品区一区二区三区 | 亚洲三级在线播放| 91国在线观看| 日本不卡视频在线| 国产欧美1区2区3区| proumb性欧美在线观看| 一区二区三区在线观看欧美| 欧美精品高清视频| 国精产品一区一区三区mba视频| 欧美精品一区二区高清在线观看| 国产·精品毛片| 亚洲欧美日韩国产一区二区三区| 欧美性感一类影片在线播放| 久久国产麻豆精品| 国产精品二区一区二区aⅴ污介绍| 色综合久久久久综合99| 麻豆精品一区二区综合av| 国产精品女人毛片| 欧美日韩精品一区二区三区蜜桃 | 欧美精品一区二区三区久久久 | 韩国精品在线观看| 亚洲欧美日韩中文播放| 精品日产卡一卡二卡麻豆| av网站免费线看精品| 亚洲成人精品在线观看| 精品福利av导航| 色国产精品一区在线观看| 蜜臀99久久精品久久久久久软件| 国产精品色一区二区三区| 欧美一卡2卡3卡4卡| 成人一区二区三区视频| 日韩高清不卡一区二区| 亚洲人成精品久久久久久| 欧美电影免费提供在线观看| 91美女片黄在线观看91美女| 精品一区二区三区免费播放| 亚洲男同性视频| 久久久www免费人成精品| 欧美日韩国产一级二级| 一本到不卡免费一区二区| 国产一区在线看| 免费看欧美女人艹b| 亚洲精品日韩综合观看成人91| 久久先锋资源网| 欧美高清一级片在线| 色综合天天综合网天天看片| 国产酒店精品激情| 蜜臀av一区二区| 天天综合网 天天综合色| 亚洲久草在线视频| 亚洲欧美在线高清| 欧美国产一区视频在线观看| 久久久噜噜噜久噜久久综合| 日韩一区二区麻豆国产| 欧美日精品一区视频| 99r国产精品| 99免费精品在线观看| 国产a级毛片一区| 国产成人综合网站| 国产精品一区二区在线观看不卡 | 国产婷婷色一区二区三区四区| 日韩欧美国产系列| 精品久久免费看| 精品国产乱码久久久久久牛牛 | 日韩欧美激情四射| 欧美成人video| 久久综合九色欧美综合狠狠| 精品国产第一区二区三区观看体验| 91麻豆精品国产自产在线 | 国产欧美日韩卡一| 亚洲国产成人在线| 亚洲人成7777| 亚洲国产欧美日韩另类综合 | 中文字幕av在线一区二区三区| 精品国产一区二区三区av性色| 久久午夜羞羞影院免费观看| 久久久精品人体av艺术| 日本一区二区免费在线观看视频 | 亚洲自拍与偷拍| 日韩和欧美一区二区三区| 日韩极品在线观看| 激情五月播播久久久精品| 国产精品综合av一区二区国产馆| 国产一区二区h| 不卡av在线网| 91超碰这里只有精品国产| 精品国产乱码久久久久久老虎| 久久久精品tv| 亚洲靠逼com| 寂寞少妇一区二区三区| 99久久免费精品| 欧美日韩一本到| 精品国一区二区三区| 中文字幕亚洲在| 日韩国产在线一| 国产·精品毛片| 51午夜精品国产| 中文字幕一区二区三区不卡在线| 亚洲国产一区二区视频| 国产乱码精品一区二区三区五月婷| 色综合久久精品| 精品欧美久久久| 亚洲一线二线三线视频| 激情欧美日韩一区二区| 色综合久久88色综合天天6| 日韩精品一区二| 一区二区三区 在线观看视频| 国模冰冰炮一区二区| 欧美日韩一二三区| 中文字幕五月欧美| 美女脱光内衣内裤视频久久网站 | 麻豆中文一区二区| 日本高清不卡在线观看| 日韩女优av电影|