Stefano Garzarella
2022-Aug-09 10:03 UTC
[RFC PATCH v3 1/9] vsock: SO_RCVLOWAT transport set callback
On Tue, Aug 09, 2022 at 09:45:47AM +0000, Arseniy Krasnov wrote:>On 09.08.2022 12:37, Arseniy Krasnov wrote: >> On 08.08.2022 13:30, Stefano Garzarella wrote: >>> On Mon, Aug 8, 2022 at 12:23 PM Stefano Garzarella <sgarzare at redhat.com> wrote: >>>> >>>> On Wed, Aug 03, 2022 at 01:51:05PM +0000, Arseniy Krasnov wrote: >>>>> This adds transport specific callback for SO_RCVLOWAT, because in some >>>>> transports it may be difficult to know current available number of bytes >>>>> ready to read. Thus, when SO_RCVLOWAT is set, transport may reject it. >>>>> >>>>> Signed-off-by: Arseniy Krasnov <AVKrasnov at sberdevices.ru> >>>>> --- >>>>> include/net/af_vsock.h | 1 + >>>>> net/vmw_vsock/af_vsock.c | 25 +++++++++++++++++++++++++ >>>>> 2 files changed, 26 insertions(+) >>>>> >>>>> diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h >>>>> index f742e50207fb..eae5874bae35 100644 >>>>> --- a/include/net/af_vsock.h >>>>> +++ b/include/net/af_vsock.h >>>>> @@ -134,6 +134,7 @@ struct vsock_transport { >>>>> u64 (*stream_rcvhiwat)(struct vsock_sock *); >>>>> bool (*stream_is_active)(struct vsock_sock *); >>>>> bool (*stream_allow)(u32 cid, u32 port); >>>>> + int (*set_rcvlowat)(struct vsock_sock *, int); >>>> >>>> checkpatch suggests to add identifier names. For some we put them in, >>>> for others we didn't, but I suggest putting them in for the new ones >>>> because I think it's clearer too. >>>> >>>> WARNING: function definition argument 'struct vsock_sock *' should also >>>> have an identifier name >>>> #25: FILE: include/net/af_vsock.h:137: >>>> + int (*set_rcvlowat)(struct vsock_sock *, int); >>>> >>>> WARNING: function definition argument 'int' should also have an identifier name >>>> #25: FILE: include/net/af_vsock.h:137: >>>> + int (*set_rcvlowat)(struct vsock_sock *, int); >>>> >>>> total: 0 errors, 2 warnings, 0 checks, 44 lines checked >>>> >>>>> >>>>> /* SEQ_PACKET. */ >>>>> ssize_t (*seqpacket_dequeue)(struct vsock_sock *vsk, struct msghdr *msg, >>>>> diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c >>>>> index f04abf662ec6..016ad5ff78b7 100644 >>>>> --- a/net/vmw_vsock/af_vsock.c >>>>> +++ b/net/vmw_vsock/af_vsock.c >>>>> @@ -2129,6 +2129,30 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, >>>>> return err; >>>>> } >>>>> >>>>> +static int vsock_set_rcvlowat(struct sock *sk, int val) >>>>> +{ >>>>> + const struct vsock_transport *transport; >>>>> + struct vsock_sock *vsk; >>>>> + int err = 0; >>>>> + >>>>> + vsk = vsock_sk(sk); >>>>> + >>>>> + if (val > vsk->buffer_size) >>>>> + return -EINVAL; >>>>> + >>>>> + transport = vsk->transport; >>>>> + >>>>> + if (!transport) >>>>> + return -EOPNOTSUPP; >>>> >>>> I don't know whether it is better in this case to write it in >>>> sk->sk_rcvlowat, maybe we can return EOPNOTSUPP only when the trasport >>>> is assigned and set_rcvlowat is not defined. This is because usually the >>>> options are set just after creation, when the transport is practically >>>> unassigned. >>>> >>>> I mean something like this: >>>> >>>> if (transport) { >>>> if (transport->set_rcvlowat) >>>> return transport->set_rcvlowat(vsk, val); >>>> else >>>> return -EOPNOTSUPP; >>>> } >>>> >>>> WRITE_ONCE(sk->sk_rcvlowat, val ? : 1); >>>> >>>> return 0; >>> >>> Since hv_sock implements `set_rcvlowat` to return EOPNOTSUPP. maybe we >>> can just do the following: >>> >>> if (transport && transport->set_rcvlowat) >>> return transport->set_rcvlowat(vsk, val); >>> >>> WRITE_ONCE(sk->sk_rcvlowat, val ? : 1); >>> return 0; >>> >>> That is, the default behavior is to set sk->sk_rcvlowat, but for >>> transports that want a different behavior, they need to define >>> set_rcvlowat() (like hv_sock). >> Hm ok, i see. I've implemented logic when non-empty transport is required, because hyperv transport >> forbids to set SO_RCVLOWAT, so user needs to call this setsockopt AFTER transport is assigned(to check >> that transport allows it. Not after socket creation as You mentioned above). Otherwise there is no sense >> in such callback - it will be never used. Also in code above - for hyperv we will have different behavior >> depends on when set_rcvlowat is called: before or after transport assignment. Is it ok? >sorry, i mean: for hyperv, if user sets sk_rcvlowat before transport is assigned, it sees 0 - success, but in fact >hyperv transport forbids this option.I see, but I think it's better to set it and not respect in hyperv (as we've practically done until now with all transports) than to prevent the setting until we assign a transport. At most when we use hyperv anyway we get notified per byte, so we should just get more notifications than we expect. Thanks, Stefano