unsigned int __nocast alloc_flags, 
gfp_t alloc_flags, 
int rxrpc_call_write_data(struct rxrpc_call *call,			  size_t sioc,			  struct kvec *siov,			  u8 rxhdr_flags,			  unsigned int __nocast alloc_flags,			  int dup_data,			  size_t *size_sent){	struct rxrpc_message *msg;	struct kvec *sptr;	size_t space, size, chunk, tmp;	char *buf;	int ret;	_enter("%p,%Zu,%p,%02x,%x,%d,%p",	       call, sioc, siov, rxhdr_flags, alloc_flags, dup_data,	       size_sent);	*size_sent = 0;	size = 0;	ret = -EINVAL;	/* can't send more if we've sent last packet from this end */	switch (call->app_call_state) {	case RXRPC_CSTATE_SRVR_SND_REPLY:	case RXRPC_CSTATE_CLNT_SND_ARGS:		break;	case RXRPC_CSTATE_ERROR:		ret = call->app_errno;	default:		goto out;	}	/* calculate how much data we've been given */	sptr = siov;	for (; sioc > 0; sptr++, sioc--) {		if (!sptr->iov_len)			continue;		if (!sptr->iov_base)			goto out;		size += sptr->iov_len;	}	_debug("- size=%Zu mtu=%Zu", size, call->conn->mtu_size);	do {		/* make sure there's a message under construction */		if (!call->snd_nextmsg) {			/* no - allocate a message with no data yet attached */			ret = rxrpc_conn_newmsg(call->conn, call,						RXRPC_PACKET_TYPE_DATA,						0, NULL, alloc_flags,						&call->snd_nextmsg);			if (ret < 0)				goto out;			_debug("- allocated new message [ds=%Zu]",			       call->snd_nextmsg->dsize);		}		msg = call->snd_nextmsg;		msg->hdr.flags |= rxhdr_flags;		/* deal with zero-length terminal packet */		if (size == 0) {			if (rxhdr_flags & RXRPC_LAST_PACKET) {				ret = rxrpc_call_flush(call);				if (ret < 0)					goto out;			}			break;		}		/* work out how much space current packet has available */		space = call->conn->mtu_size - msg->dsize;		chunk = min(space, size);		_debug("- [before] space=%Zu chunk=%Zu", space, chunk);		while (!siov->iov_len)			siov++;		/* if we are going to have to duplicate the data then coalesce		 * it too */		if (dup_data) {			/* don't allocate more that 1 page at a time */			if (chunk > PAGE_SIZE)				chunk = PAGE_SIZE;			/* allocate a data buffer and attach to the message */			buf = kmalloc(chunk, alloc_flags);			if (unlikely(!buf)) {				if (msg->dsize ==				    sizeof(struct rxrpc_header)) {					/* discard an empty msg and wind back					 * the seq counter */					rxrpc_put_message(msg);					call->snd_nextmsg = NULL;					call->snd_seq_count--;				}				ret = -ENOMEM;				goto out;			}			tmp = msg->dcount++;			set_bit(tmp, &msg->dfree);			msg->data[tmp].iov_base = buf;			msg->data[tmp].iov_len = chunk;			msg->dsize += chunk;			*size_sent += chunk;			size -= chunk;			/* load the buffer with data */			while (chunk > 0) {				tmp = min(chunk, siov->iov_len);				memcpy(buf, siov->iov_base, tmp);				buf += tmp;				siov->iov_base += tmp;				siov->iov_len -= tmp;				if (!siov->iov_len)					siov++;				chunk -= tmp;			}		}		else {			/* we want to attach the supplied buffers directly */			while (chunk > 0 &&			       msg->dcount < RXRPC_MSG_MAX_IOCS) {				tmp = msg->dcount++;				msg->data[tmp].iov_base = siov->iov_base;				msg->data[tmp].iov_len = siov->iov_len;				msg->dsize += siov->iov_len;				*size_sent += siov->iov_len;				size -= siov->iov_len;				chunk -= siov->iov_len;				siov++;			}		}		_debug("- [loaded] chunk=%Zu size=%Zu", chunk, size);		/* dispatch the message when full, final or requesting ACK */		if (msg->dsize >= call->conn->mtu_size || rxhdr_flags) {			ret = rxrpc_call_flush(call);			if (ret < 0)				goto out;		}	} while(size > 0);	ret = 0; out:	_leave(" = %d (%Zd queued, %Zd rem)", ret, *size_sent, size);	return ret;} /* end rxrpc_call_write_data() */
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/dd0fc66fb33cd610bc1a5db8a5e232d34879b4d7/call.c/clean/net/rxrpc/call.c