| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Shared Memory Communications over RDMA (SMC-R) and RoCE |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 20 | 21 | |
|---|
| 21 | 22 | #include "smc.h" |
|---|
| 22 | 23 | #include "smc_core.h" |
|---|
| 24 | + |
|---|
| 25 | +struct smc_diag_dump_ctx { |
|---|
| 26 | + int pos[2]; |
|---|
| 27 | +}; |
|---|
| 28 | + |
|---|
| 29 | +static struct smc_diag_dump_ctx *smc_dump_context(struct netlink_callback *cb) |
|---|
| 30 | +{ |
|---|
| 31 | + return (struct smc_diag_dump_ctx *)cb->ctx; |
|---|
| 32 | +} |
|---|
| 23 | 33 | |
|---|
| 24 | 34 | static void smc_gid_be16_convert(__u8 *buf, u8 *gid_raw) |
|---|
| 25 | 35 | { |
|---|
| .. | .. |
|---|
| 192 | 202 | } |
|---|
| 193 | 203 | |
|---|
| 194 | 204 | static int smc_diag_dump_proto(struct proto *prot, struct sk_buff *skb, |
|---|
| 195 | | - struct netlink_callback *cb) |
|---|
| 205 | + struct netlink_callback *cb, int p_type) |
|---|
| 196 | 206 | { |
|---|
| 207 | + struct smc_diag_dump_ctx *cb_ctx = smc_dump_context(cb); |
|---|
| 197 | 208 | struct net *net = sock_net(skb->sk); |
|---|
| 209 | + int snum = cb_ctx->pos[p_type]; |
|---|
| 198 | 210 | struct nlattr *bc = NULL; |
|---|
| 199 | 211 | struct hlist_head *head; |
|---|
| 212 | + int rc = 0, num = 0; |
|---|
| 200 | 213 | struct sock *sk; |
|---|
| 201 | | - int rc = 0; |
|---|
| 202 | 214 | |
|---|
| 203 | 215 | read_lock(&prot->h.smc_hash->lock); |
|---|
| 204 | 216 | head = &prot->h.smc_hash->ht; |
|---|
| .. | .. |
|---|
| 208 | 220 | sk_for_each(sk, head) { |
|---|
| 209 | 221 | if (!net_eq(sock_net(sk), net)) |
|---|
| 210 | 222 | continue; |
|---|
| 223 | + if (num < snum) |
|---|
| 224 | + goto next; |
|---|
| 211 | 225 | rc = __smc_diag_dump(sk, skb, cb, nlmsg_data(cb->nlh), bc); |
|---|
| 212 | | - if (rc) |
|---|
| 213 | | - break; |
|---|
| 226 | + if (rc < 0) |
|---|
| 227 | + goto out; |
|---|
| 228 | +next: |
|---|
| 229 | + num++; |
|---|
| 214 | 230 | } |
|---|
| 215 | 231 | |
|---|
| 216 | 232 | out: |
|---|
| 217 | 233 | read_unlock(&prot->h.smc_hash->lock); |
|---|
| 234 | + cb_ctx->pos[p_type] = num; |
|---|
| 218 | 235 | return rc; |
|---|
| 219 | 236 | } |
|---|
| 220 | 237 | |
|---|
| .. | .. |
|---|
| 222 | 239 | { |
|---|
| 223 | 240 | int rc = 0; |
|---|
| 224 | 241 | |
|---|
| 225 | | - rc = smc_diag_dump_proto(&smc_proto, skb, cb); |
|---|
| 242 | + rc = smc_diag_dump_proto(&smc_proto, skb, cb, SMCPROTO_SMC); |
|---|
| 226 | 243 | if (!rc) |
|---|
| 227 | | - rc = smc_diag_dump_proto(&smc_proto6, skb, cb); |
|---|
| 228 | | - return rc; |
|---|
| 244 | + smc_diag_dump_proto(&smc_proto6, skb, cb, SMCPROTO_SMC6); |
|---|
| 245 | + return skb->len; |
|---|
| 229 | 246 | } |
|---|
| 230 | 247 | |
|---|
| 231 | 248 | static int smc_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) |
|---|