diff options
Diffstat (limited to 'net/core/skmsg.c')
| -rw-r--r-- | net/core/skmsg.c | 20 | 
1 files changed, 15 insertions, 5 deletions
diff --git a/net/core/skmsg.c b/net/core/skmsg.c index cf390e0aa73d..ad31e4e53d0a 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -270,18 +270,28 @@ void sk_msg_trim(struct sock *sk, struct sk_msg *msg, int len)  	msg->sg.data[i].length -= trim;  	sk_mem_uncharge(sk, trim); +	/* Adjust copybreak if it falls into the trimmed part of last buf */ +	if (msg->sg.curr == i && msg->sg.copybreak > msg->sg.data[i].length) +		msg->sg.copybreak = msg->sg.data[i].length;  out: -	/* If we trim data before curr pointer update copybreak and current -	 * so that any future copy operations start at new copy location. +	sk_msg_iter_var_next(i); +	msg->sg.end = i; + +	/* If we trim data a full sg elem before curr pointer update +	 * copybreak and current so that any future copy operations +	 * start at new copy location.  	 * However trimed data that has not yet been used in a copy op  	 * does not require an update.  	 */ -	if (msg->sg.curr >= i) { +	if (!msg->sg.size) { +		msg->sg.curr = msg->sg.start; +		msg->sg.copybreak = 0; +	} else if (sk_msg_iter_dist(msg->sg.start, msg->sg.curr) >= +		   sk_msg_iter_dist(msg->sg.start, msg->sg.end)) { +		sk_msg_iter_var_prev(i);  		msg->sg.curr = i;  		msg->sg.copybreak = msg->sg.data[i].length;  	} -	sk_msg_iter_var_next(i); -	msg->sg.end = i;  }  EXPORT_SYMBOL_GPL(sk_msg_trim);  | 
