⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iscsi-network.c

📁 ISCSI user client software.Client would be used to access the IPSAN server.
💻 C
字号:
/* * iSCSI driver for Linux * Copyright (C) 2001 Cisco Systems, Inc. * Copyright (C) 2004 Mike Christie * Copyright (C) 2004 IBM Corporation * maintained by linux-iscsi-devel@lists.sourceforge.net * * 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. * * $Id: iscsi-network.c,v 1.17 2005/02/14 05:42:30 smithan Exp $ * * Contains functions to handle socket operations */#include <linux/tcp.h>#include <linux/uio.h>#include "iscsi-session.h"#include "iscsi-sfnet.h"/* create and connect a new socket for this session */intiscsi_connect(struct iscsi_session *session){	struct socket *socket;	int arg = 1;	int rc;	if (session->socket)		return 0;	rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &socket);	if (rc < 0) {		iscsi_host_err(session, "Failed to create socket, rc %d\n", rc);		return rc;	}	session->socket = socket;	socket->sk->sk_allocation = GFP_ATOMIC;	/* no delay in sending */	rc = socket->ops->setsockopt(socket, IPPROTO_TCP, TCP_NODELAY,				     (char *)&arg, sizeof(arg));	if (rc) {		iscsi_host_err(session, "Failed to setsockopt TCP_NODELAY, rc "			       "%d\n", rc);		goto done;	}	if (session->tcp_window_size) {		/*		 * Should we be accessing the sk_recv/send_buf directly like		 * NFS (sock_setsockopt will be bounded by the sysctl limits)?		 */		sock_setsockopt(socket, SOL_SOCKET, SO_RCVBUF,			        (char *)&session->tcp_window_size,				sizeof(session->tcp_window_size));		sock_setsockopt(socket, SOL_SOCKET, SO_SNDBUF,			        (char *)&session->tcp_window_size,				sizeof(session->tcp_window_size));	}	rc = socket->ops->connect(socket, &session->addr,				  sizeof(struct sockaddr), 0); done:	if (rc) {		sock_release(socket);		session->socket = NULL;	}	return rc;}voidiscsi_disconnect(struct iscsi_session *session){	if (session->socket) {		sock_release(session->socket);		session->socket = NULL;	}}/* * decode common network errno values into more useful strings. * strerror would be nice right about now. */static char *iscsi_strerror(int errno){	switch (errno) {	case EIO:		return "I/O error";	case EINTR:		return "Interrupted system call";	case ENXIO:		return "No such device or address";	case EFAULT:		return "Bad address";	case EBUSY:		return "Device or resource busy";	case EINVAL:		return "Invalid argument";	case EPIPE:		return "Broken pipe";	case ENONET:		return "Machine is not on the network";	case ECOMM:		return "Communication error on send";	case EPROTO:		return "Protocol error";	case ENOTUNIQ:		return "Name not unique on network";	case ENOTSOCK:		return "Socket operation on non-socket";	case ENETDOWN:		return "Network is down";	case ENETUNREACH:		return "Network is unreachable";	case ENETRESET:		return "Network dropped connection because of reset";	case ECONNABORTED:		return "Software caused connection abort";	case ECONNRESET:		return "Connection reset by peer";	case ESHUTDOWN:		return "Cannot send after shutdown";	case ETIMEDOUT:		return "Connection timed out";	case ECONNREFUSED:		return "Connection refused";	case EHOSTDOWN:		return "Host is down";	case EHOSTUNREACH:		return "No route to host";	default:		return "";	}}/** * iscsi_sendpage - Transmit data using sock->ops->sendpage * @session: iscsi_session to the target * @flags: MSG_MORE or 0 * @pg: page to send * @pg_offset: offset in page * @len: length of the data to be transmitted. **/intiscsi_sendpage(struct iscsi_session *session, int flags, struct page *pg,	       unsigned int pg_offset, unsigned int len){	struct socket *sock = session->socket;	int rc;	rc = sock->ops->sendpage(sock, pg, pg_offset, len, flags);	if (signal_pending(current))		return ISCSI_IO_INTR;	else if (rc != len) {		if (rc == 0)			iscsi_host_err(session, "iscsi_sendpage() failed due "				       "to connection closed by target\n");		else if (rc < 0)			iscsi_host_err(session, "iscsi_sendpage() failed with "				       "rc %d: %s\n", rc, iscsi_strerror(-rc));		else			iscsi_host_warn(session, "iscsi_sendpage() failed due "					"to short write of %d of %u\n", rc,					len);		return ISCSI_IO_ERR;	}	return ISCSI_IO_SUCCESS;}/** * iscsi_send/recvmsg - recv or send a iSCSI PDU, or portion thereof * @session: iscsi session * @iov: contains list of buffers to receive data in * @iovn: number of buffers in IO vec * @size: total size of data to be received * * Note: *    tcp_*msg() might be interrupted because we got *    sent a signal, e.g. SIGHUP from iscsi_drop_session().  In *    this case, we most likely did not receive all the data, and *    we should just bail out.  No need to log any message since *    this is expected behavior. **/intiscsi_recvmsg(struct iscsi_session *session, struct kvec *iov, size_t iovn,	      size_t size){	struct msghdr msg;	int rc;		memset(&msg, 0, sizeof(msg));	rc = kernel_recvmsg(session->socket, &msg, iov, iovn, size,			    MSG_WAITALL);	if (signal_pending(current))		return ISCSI_IO_INTR;	else if (rc != size) {		if (rc == 0)			iscsi_host_err(session, "iscsi_recvmsg() failed due "				       "to connection closed by target\n");		else if (rc < 0)			iscsi_host_err(session, "iscsi_recvmsg() failed with "				       "rc %d: %s\n", rc, iscsi_strerror(-rc));		else			iscsi_host_warn(session, "iscsi_recvmsg() failed due "					"to short read of %d\n", rc);		return ISCSI_IO_ERR;	}	return ISCSI_IO_SUCCESS;}intiscsi_sendmsg(struct iscsi_session *session, struct kvec *iov, size_t iovn,	      size_t size){	struct msghdr msg;	int rc;	memset(&msg, 0, sizeof(msg));	rc = kernel_sendmsg(session->socket, &msg, iov, iovn, size);	if (signal_pending(current))		return ISCSI_IO_INTR;	else if (rc != size) {		if (rc == 0)			iscsi_host_err(session, "iscsi_sendmsg() failed due "				       "to connection closed by target\n");		else if (rc < 0)			iscsi_host_err(session, "iscsi_sendmsg() failed with "				       "rc %d: %s\n", rc, iscsi_strerror(-rc));		else			iscsi_host_warn(session, "iscsi_sendmsg() failed due "					"to short write of %d\n", rc);		return ISCSI_IO_ERR;	}	return ISCSI_IO_SUCCESS;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -