fix build with v6.5
[metze/linux/smbdirect.git] / smbdirect.h
1 // SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause)
2 /*
3  * SMB-Direct subsystem for Linux
4  *
5  * This implements [MS-SMBD] SMB2 Remote Direct Memory Access (RDMA) Transport Protocol
6  *
7  * Authors: Stefan Metzmacher <metze@samba.org>
8  *
9  * Copyright (c) 2017-2018 Stefan Metzmacher
10  *
11  * This software is available to you under a choice of one of two
12  * licenses.  You may choose to be licensed under the terms of the GNU
13  * General Public License (GPL) Version 2, available from the file
14  * COPYING in the main directory of this source tree, or the
15  * BSD license below:
16  *
17  *   Redistribution and use in source and binary forms, with or
18  *   without modification, are permitted provided that the following
19  *   conditions are met:
20  *
21  *   - Redistributions of source code must retain the above copyright notice,
22  *     this list of conditions and the following disclaimer.
23  *
24  *   - Redistributions in binary form must reproduce the above copyright
25  *     notice, this list of conditions and the following disclaimer in the
26  *     documentation and/or other materials provided with the distribution.
27  *
28  *   - Neither the name of the copyright holder nor the names of its contributors
29  *     may be used to endorse or promote products derived from this software without
30  *     specific prior written permission.
31  *
32  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
36  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
37  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
38  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39  * SOFTWARE.
40  */
41
42 #ifndef SMBDIRECT_H
43 #define SMBDIRECT_H
44
45 #ifndef __KERNEL__
46 #include <stdbool.h>
47 #include <stdint.h>
48 #include <sys/types.h>
49 #include <linux/types.h>
50 #include <sys/socket.h>
51 #include <sys/ioctl.h>
52 #include <unistd.h>
53 #include <fcntl.h>
54 #include <string.h>
55 #include <errno.h>
56 #include <assert.h>
57 #ifndef __user
58 #define __user
59 #endif
60 #ifndef __packed
61 #define __packed __attribute__((packed))
62 #endif
63 #ifndef BUG_ON
64 #define BUG_ON(x) assert(!(x))
65 #endif
66 #ifndef BUILD_BUG_ON
67 #define BUILD_BUG_ON(x)
68 #endif
69 #endif /* !__KERNEL__ */
70
71 /*
72  * userspace:
73  *
74  *   int socket(int family, int type, int protocol);
75  *
76  * kernel:
77  *
78  *   int sock_create_kern(struct net *net,
79  *                        int family, int type, int protocol,
80  *                        struct socket **res);
81  *
82  * family: PF_SMBDIRECT
83  * type: SOCK_STREAM, together with SOCK_CLOEXEC SOCK_NONBLOCK
84  * protocol: address family + protocol flavor
85  *
86  * address family: AF_INET or AF_INET6
87  * protocol flavor: SMBDIRECT_FLAVOR_AUTO
88  */
89 #ifndef PF_SMBDIRECT
90 /*
91  * until we get an official number,
92  * we use the unused PF_WANPIPE
93  */
94 #define PF_SMBDIRECT PF_WANPIPE
95 #define SOL_SMBDIRECT 999
96 #endif /* ! PF_SMBDIRECT */
97
98 /*
99  * AF_INET, AF_INET6 and AF_IB are below 0xff
100  */
101 #define SMBDIRECT_FAMILY_MASK                0x000000ff
102 /*
103  * For now just auto use iWarp and ROCE
104  */
105 #define SMBDIRECT_FLAVOR_MASK                0x0000f000
106 #define SMBDIRECT_FLAVOR_AUTO                0x00000000
107 /*
108  * Additional hints/flags
109  */
110 #define SMBDIRECT_FLAGS_MASK                 0x7fff0000
111 #define SMBDIRECT_FLAGS_VALID ( \
112         0)
113
114 #define SMBDIRECT_PROTOCOL_INVALID_MASK ~((unsigned)( \
115         SMBDIRECT_FAMILY_MASK | \
116         SMBDIRECT_FLAVOR_MASK | \
117         SMBDIRECT_FLAGS_MASK | \
118         0))
119
120 enum {
121         __SMBDIRECT_CONNECTION_PARAMETERS = 100,
122
123         __SMBDIRECT_BUFFER_UNREGISTER = 200,
124         __SMBDIRECT_BUFFER_REGISTER_READ = 201,
125         __SMBDIRECT_BUFFER_REGISTER_WRITE = 202,
126
127         __SMBDIRECT_BUFFER_REMOTE_INVALIDATE = 300,
128         __SMBDIRECT_BUFFER_REMOTE_READ = 301,
129         __SMBDIRECT_BUFFER_REMOTE_WRITE = 302,
130 };
131
132 struct smbdirect_connection_parameters {
133         __u16 recv_credit_max;
134         __u16 send_credit_target;
135         __u32 max_send_size;
136         __u32 max_fragmented_send_size;
137         __u32 max_recv_size;
138         __u32 max_fragmented_recv_size;
139         __u32 max_read_write_size;
140         __u32 keepalive_interval;
141 } __packed;
142 #define SMBDIRECT_CONNECTION_PARAMETERS \
143         _IOWR('S', __SMBDIRECT_CONNECTION_PARAMETERS, \
144                 struct smbdirect_connection_parameters)
145
146 /*
147  * int smbdirect_connection_get_parameters(int sockfd,
148  *                               struct smbdirect_connection_parameters *params)
149  */
150 #ifndef __KERNEL__
151 static inline int smbdirect_connection_get_parameters(int sockfd,
152                 struct smbdirect_connection_parameters *_params)
153 {
154         struct smbdirect_connection_parameters params = {
155                 .keepalive_interval = 0,
156         };
157         socklen_t optlen = sizeof(params);
158         int rc;
159
160         rc = getsockopt(sockfd, SOL_SMBDIRECT, SMBDIRECT_CONNECTION_PARAMETERS,
161                         &params, &optlen);
162         if (rc != 0) {
163                 switch (errno) {
164                 case 0:
165                         errno = ENOPROTOOPT;
166                         break;
167                 }
168                 return -1;
169         }
170
171         if (optlen != sizeof(params)) {
172                 errno = EBADMSG;
173                 return -1;
174         }
175
176         *_params = params;
177         return 0;
178 }
179 #endif /* !__KERNEL__ */
180
181 #ifdef __KERNEL__
182 int smbdirect_kern_connection_get_parameters(struct socket *sock,
183                                              struct smbdirect_connection_parameters *params);
184 #endif /* __KERNEL__ */
185
186 struct smbdirect_buffer_descriptor_v1 {
187         __le64 offset;
188         __le32 token;
189         __le32 length;
190 } __packed;
191
192 struct smbdirect_buffer_descriptors_v1 {
193 #define SMBDIRECT_BUFFER_ALLOW_READ  0x00000001
194 #define SMBDIRECT_BUFFER_ALLOW_WRITE 0x00000002
195 #define SMBDIRECT_BUFFER_INVALIDATE  0x00000004
196 #define SMBDIRECT_BUFFER_REMOTE      0x00000008
197 #define SMBDIRECT_BUFFER_DEFINED_FLAGS ( \
198         SMBDIRECT_BUFFER_ALLOW_READ | \
199         SMBDIRECT_BUFFER_ALLOW_WRITE | \
200         SMBDIRECT_BUFFER_INVALIDATE | \
201         SMBDIRECT_BUFFER_REMOTE | \
202         0)
203         __u32 flags;
204 /* (UINT16_MAX / sizeof(smbdirect_buffer_descriptor_v1)) = 4096 */
205 #define _SMBDIRECT_BUFFER_COUNT_MAX 4096
206         __u16 max_count;
207         __u16 count;
208         struct smbdirect_buffer_descriptor_v1 array[];
209 } __packed;
210
211 struct smbdirect_buffer_descriptors_v1_fast {
212         struct smbdirect_buffer_descriptors_v1 hdr;
213 #ifndef SMBDIRECT_BUFFER_COUNT_FAST
214 #define SMBDIRECT_BUFFER_COUNT_FAST 32
215 #endif
216         struct smbdirect_buffer_descriptor_v1 __fast_array[SMBDIRECT_BUFFER_COUNT_FAST];
217 } __packed;
218
219 #define SMBDIRECT_BUFFER_DESCRIPTORS_V1_FAST_INIT { \
220         .hdr = { \
221                 .max_count = SMBDIRECT_BUFFER_COUNT_FAST, \
222         }, \
223 }
224
225 #define SMBDIRECT_BUFFER_DESCRIPTORS_V1_SIZE(count) \
226         (sizeof(struct smbdirect_buffer_descriptors_v1) + \
227          sizeof(struct smbdirect_buffer_descriptor_v1)*count)
228
229 static inline struct iovec smbdirect_buffer_descriptors_v1_channel(
230                                 const struct smbdirect_buffer_descriptors_v1 *descs)
231 {
232         struct iovec iov;
233
234         BUG_ON(descs->count == 0);
235
236         iov = (struct iovec) {
237                 .iov_base = (void *)(uintptr_t)(const void*)descs->array,
238                 .iov_len = sizeof(descs->array[0])*descs->count,
239         };
240
241         return iov;
242 }
243
244 struct smbdirect_cmsg_buffer {
245         uint8_t msg_control[CMSG_SPACE(24)];
246 };
247
248 static inline void __smbdirect_cmsg_prepare(struct msghdr *msg,
249                                             struct smbdirect_cmsg_buffer *cbuffer,
250                                             int cmsg_type,
251                                             const void *payload,
252                                             size_t payloadlen)
253 {
254         size_t cmsg_space = CMSG_SPACE(payloadlen);
255         size_t cmsg_len = CMSG_LEN(payloadlen);
256         struct cmsghdr *cmsg = NULL;
257         void *dataptr = NULL;
258
259         BUILD_BUG_ON(cmsg_space > sizeof(cbuffer->msg_control));
260         BUG_ON(cmsg_space > sizeof(cbuffer->msg_control));
261
262         memset(cbuffer, 0, sizeof(*cbuffer));
263
264         msg->msg_control = cbuffer->msg_control;
265         msg->msg_controllen = cmsg_space;
266
267         cmsg = CMSG_FIRSTHDR(msg);
268         cmsg->cmsg_level = SOL_SMBDIRECT;
269         cmsg->cmsg_type = cmsg_type;
270         cmsg->cmsg_len = cmsg_len;
271         dataptr = CMSG_DATA(cmsg);
272         memcpy(dataptr, payload, payloadlen);
273         msg->msg_controllen = cmsg->cmsg_len;
274 }
275
276 static inline ssize_t __smbdirect_cmsg_extract(const struct msghdr *_msg,
277                                                int cmsg_type,
278                                                void *_payload,
279                                                size_t payloadmin,
280                                                size_t payloadmax)
281 {
282         struct msghdr *msg = (struct msghdr *)(uintptr_t)(const void *)_msg;
283         uint8_t *payload = (uint8_t *)_payload;
284         const size_t cmsg_len_hdr = CMSG_LEN(0);
285         size_t cmsg_len_min = CMSG_LEN(payloadmin);
286         size_t cmsg_len_max = CMSG_LEN(payloadmax);
287         struct cmsghdr *cmsg = NULL;
288         size_t payloadlen;
289
290         //BUILD_BUG_ON(cmsg_len_min > cmsg_len_max);
291         BUG_ON(cmsg_len_min > cmsg_len_max);
292
293         for (cmsg = CMSG_FIRSTHDR(msg);
294              cmsg != NULL;
295              cmsg = CMSG_NXTHDR(msg, cmsg))
296         {
297                 if (cmsg->cmsg_level != SOL_SMBDIRECT) {
298                         continue;
299                 }
300
301                 if (cmsg->cmsg_type != cmsg_type) {
302                         continue;
303                 }
304
305                 if (cmsg->cmsg_len < cmsg_len_min) {
306                         return -EBADMSG;
307                 }
308
309                 if (cmsg->cmsg_len > cmsg_len_max) {
310                         return -EMSGSIZE;
311                 }
312
313                 payloadlen = cmsg->cmsg_len - cmsg_len_hdr;
314                 if (payloadlen > 0) {
315                         const void *dataptr = CMSG_DATA(cmsg);
316                         memcpy(payload, dataptr, payloadlen);
317                 }
318                 if (payloadlen < payloadmax) {
319                         memset(payload + payloadlen, 0,
320                                payloadmax - payloadlen);
321                 }
322                 return payloadlen;
323         }
324
325         return -ENOMSG;
326 }
327
328 struct smbdirect_buffer_unregister_args {
329         __u64 local;
330 } __packed;
331 #define SMBDIRECT_BUFFER_UNREGISTER_CMSG_TYPE \
332         _IOWR('S', __SMBDIRECT_BUFFER_UNREGISTER, \
333                 struct smbdirect_buffer_unregister_args)
334
335 static inline void smbdirect_buffer_unregister_cmsg_prepare(struct msghdr *msg,
336                                                             int *pmsg_flags,
337                                                             struct smbdirect_cmsg_buffer *cbuffer,
338                                                             struct smbdirect_buffer_descriptors_v1 *descs)
339 {
340         struct smbdirect_buffer_unregister_args args = {
341                 .local = (uintptr_t)descs,
342         };
343
344         __smbdirect_cmsg_prepare(msg, cbuffer,
345                                  SMBDIRECT_BUFFER_UNREGISTER_CMSG_TYPE,
346                                  &args, sizeof(args));
347         *pmsg_flags |= MSG_OOB;
348 }
349
350 struct smbdirect_buffer_register_read_args {
351         __u64 local;
352 } __packed;
353 #define SMBDIRECT_BUFFER_REGISTER_READ_CMSG_TYPE \
354         _IOWR('S', __SMBDIRECT_BUFFER_REGISTER_READ, \
355                 struct smbdirect_buffer_register_read_args)
356
357 static inline void smbdirect_buffer_register_read_cmsg_prepare(struct msghdr *msg,
358                                                                int *pmsg_flags,
359                                                                struct smbdirect_cmsg_buffer *cbuffer,
360                                                                struct smbdirect_buffer_descriptors_v1 *descs)
361 {
362         struct smbdirect_buffer_register_read_args args = {
363                 .local = (uintptr_t)descs,
364         };
365
366         __smbdirect_cmsg_prepare(msg, cbuffer,
367                                  SMBDIRECT_BUFFER_REGISTER_READ_CMSG_TYPE,
368                                  &args, sizeof(args));
369         *pmsg_flags |= MSG_OOB;
370 }
371
372 struct smbdirect_buffer_register_write_args {
373         __u64 local;
374 } __packed;
375 #define SMBDIRECT_BUFFER_REGISTER_WRITE_CMSG_TYPE \
376         _IOWR('S', __SMBDIRECT_BUFFER_REGISTER_WRITE, \
377                 struct smbdirect_buffer_register_write_args)
378
379 static inline void smbdirect_buffer_register_write_cmsg_prepare(struct msghdr *msg,
380                                                                 int *pmsg_flags,
381                                                                 struct smbdirect_cmsg_buffer *cbuffer,
382                                                                 struct smbdirect_buffer_descriptors_v1 *descs)
383 {
384         struct smbdirect_buffer_register_write_args args = {
385                 .local = (uintptr_t)descs,
386         };
387
388         __smbdirect_cmsg_prepare(msg, cbuffer,
389                                  SMBDIRECT_BUFFER_REGISTER_WRITE_CMSG_TYPE,
390                                  &args, sizeof(args));
391         *pmsg_flags |= MSG_OOB;
392 }
393
394 struct smbdirect_buffer_remote_invalidate_args {
395         struct smbdirect_buffer_descriptor_v1 first_desc;
396 } __packed;
397 #define SMBDIRECT_BUFFER_REMOTE_INVALIDATE_CMSG_TYPE \
398         _IOW('S', __SMBDIRECT_BUFFER_REMOTE_INVALIDATE, \
399                 struct smbdirect_buffer_remote_invalidate_args)
400
401 static inline void smbdirect_buffer_remote_invalidate_cmsg_prepare(struct msghdr *msg,
402                                                                    struct smbdirect_cmsg_buffer *cbuffer,
403                                                                    const struct smbdirect_buffer_descriptor_v1 *desc)
404 {
405         struct smbdirect_buffer_remote_invalidate_args args = {
406                 .first_desc = *desc,
407         };
408
409         __smbdirect_cmsg_prepare(msg, cbuffer,
410                                  SMBDIRECT_BUFFER_REMOTE_INVALIDATE_CMSG_TYPE,
411                                  &args, sizeof(args));
412 }
413
414 struct smbdirect_buffer_remote_write_args {
415         __u64 remote;
416         __s32 splice_from_fd;
417 } __packed;
418 #define SMBDIRECT_BUFFER_REMOTE_WRITE_CMSG_TYPE \
419         _IOW('S', __SMBDIRECT_BUFFER_REMOTE_WRITE, \
420                 struct smbdirect_buffer_remote_write_args)
421
422 static inline void smbdirect_buffer_remote_write_cmsg_prepare(struct msghdr *msg,
423                                                               int *pmsg_flags,
424                                                               struct smbdirect_cmsg_buffer *cbuffer,
425                                                               int splice_from_fd,
426                                                               const struct smbdirect_buffer_descriptors_v1 *descs)
427 {
428         struct smbdirect_buffer_remote_write_args args = {
429                 .remote = (uintptr_t)descs,
430                 .splice_from_fd = splice_from_fd,
431         };
432
433         __smbdirect_cmsg_prepare(msg, cbuffer,
434                                  SMBDIRECT_BUFFER_REMOTE_WRITE_CMSG_TYPE,
435                                  &args, sizeof(args));
436         *pmsg_flags |= MSG_OOB;
437 }
438
439 struct smbdirect_buffer_remote_read_args {
440         __u64 remote;
441         __s32 splice_to_fd;
442 } __packed;
443 #define SMBDIRECT_BUFFER_REMOTE_READ_CMSG_TYPE \
444         _IOW('S', __SMBDIRECT_BUFFER_REMOTE_READ, struct smbdirect_buffer_remote_read_args)
445
446 static inline void smbdirect_buffer_remote_read_cmsg_prepare(struct msghdr *msg,
447                                                              int *pmsg_flags,
448                                                              struct smbdirect_cmsg_buffer *cbuffer,
449                                                              int splice_to_fd,
450                                                              const struct smbdirect_buffer_descriptors_v1 *descs)
451 {
452         struct smbdirect_buffer_remote_read_args args = {
453                 .remote = (uintptr_t)descs,
454                 .splice_to_fd = splice_to_fd,
455         };
456
457         __smbdirect_cmsg_prepare(msg, cbuffer,
458                                  SMBDIRECT_BUFFER_REMOTE_READ_CMSG_TYPE,
459                                  &args, sizeof(args));
460         *pmsg_flags |= MSG_OOB;
461 }
462
463 /*
464  * ssize_t smbdirect_rdma_v1_register_read(int sockfd,
465  *                                  struct smbdirect_buffer_descriptors_v1 *local,
466  *                                  int iovcnt,
467  *                                  const struct iovec *iov)
468  *
469  * The remote peer can read from this buffers
470  */
471 #ifndef __KERNEL__
472 static inline ssize_t smbdirect_rdma_v1_register_read(int sockfd,
473                                 struct smbdirect_buffer_descriptors_v1 __user *local,
474                                 int iovcnt,
475                                 const struct iovec __user *iov)
476 {
477         struct smbdirect_cmsg_buffer cbuffer;
478         struct msghdr msg = {
479                 .msg_iovlen = iovcnt,
480                 .msg_iov = (struct iovec *)(uintptr_t)(const void *)iov,
481         };
482         int msg_flags = 0;
483
484         smbdirect_buffer_register_read_cmsg_prepare(&msg, &msg_flags, &cbuffer, local);
485
486         return sendmsg(sockfd, &msg, msg_flags);
487 }
488 #endif /* !__KERNEL__ */
489
490 /*
491  * ssize_t smbdirect_rdma_v1_register_write(int sockfd,
492  *                                  struct smbdirect_buffer_descriptors_v1 *local,
493  *                                  int iovcnt,
494  *                                  struct iovec *iov)
495  *
496  * The remote peer can write to this buffers
497  */
498 #ifndef __KERNEL__
499 static inline ssize_t smbdirect_rdma_v1_register_write(int sockfd,
500                                 struct smbdirect_buffer_descriptors_v1 __user *local,
501                                 int iovcnt,
502                                 struct iovec __user *iov)
503 {
504         struct smbdirect_cmsg_buffer cbuffer;
505         struct msghdr msg = {
506                 .msg_iovlen = iovcnt,
507                 .msg_iov = iov,
508         };
509         int msg_flags = 0;
510
511         smbdirect_buffer_register_write_cmsg_prepare(&msg, &msg_flags, &cbuffer, local);
512
513         return recvmsg(sockfd, &msg, msg_flags);
514 }
515 #endif /* !__KERNEL__ */
516 #ifdef __KERNEL__
517 extern ssize_t smbdirect_kern_rdma_v1_register_pages(struct socket *sock,
518                                         struct smbdirect_buffer_descriptors_v1 *local,
519                                         struct page *pages[], int num_pages,
520                                         int pagesz, int fp_ofs, int lp_len);
521 #endif /* __KERNEL__ */
522
523 /*
524  * ssize_t smbdirect_rdma_v1_unregister(int sockfd,
525  *                                      struct smbdirect_buffer_descriptors_v1 *local)
526  */
527 #ifndef __KERNEL__
528 static inline ssize_t smbdirect_rdma_v1_unregister(int sockfd,
529                                 struct smbdirect_buffer_descriptors_v1 __user *local)
530 {
531         struct smbdirect_cmsg_buffer cbuffer;
532         struct msghdr msg = {
533                 .msg_iovlen = 0,
534         };
535         int msg_flags = 0;
536
537         smbdirect_buffer_unregister_cmsg_prepare(&msg, &msg_flags, &cbuffer, local);
538
539         return sendmsg(sockfd, &msg, msg_flags);
540 }
541 #endif /* !__KERNEL__ */
542
543 #ifdef __KERNEL__
544 ssize_t smbdirect_kern_rdma_v1_unregister(struct socket *sock,
545                                           struct smbdirect_buffer_descriptors_v1 *local);
546 #endif /* __KERNEL__ */
547
548 /*
549  * ssize_t smbdirect_rdma_v1_writev(int sockfd,
550  *                                  const struct smbdirect_buffer_descriptors_v1 *remote,
551  *                                  int iovcnt,
552  *                                  const struct iovec *iov)
553  *
554  * Writes into the remote buffer.
555  */
556 #ifndef __KERNEL__
557 static inline ssize_t smbdirect_rdma_v1_writev(int sockfd,
558                                 const struct smbdirect_buffer_descriptors_v1 __user *remote,
559                                 int iovcnt,
560                                 const struct iovec __user *iov)
561 {
562         struct smbdirect_cmsg_buffer cbuffer;
563         struct msghdr msg = {
564                 .msg_iovlen = iovcnt,
565                 .msg_iov = (struct iovec *)(uintptr_t)(const void *)iov,
566         };
567         int msg_flags = 0;
568
569         smbdirect_buffer_remote_write_cmsg_prepare(&msg, &msg_flags, &cbuffer, -1, remote);
570
571         return sendmsg(sockfd, &msg, msg_flags);
572 }
573 #endif /* !__KERNEL__ */
574
575 #ifdef __KERNEL__
576 ssize_t smbdirect_kern_rdma_v1_writev(struct socket *sock,
577                                       const struct smbdirect_buffer_descriptors_v1 *remote,
578                                       size_t size,
579                                       struct iov_iter *iter);
580 #endif /* __KERNEL__ */
581
582 /*
583  * ssize_t smbdirect_rdma_v1_readv(int sockfd,
584  *                                 const struct smbdirect_buffer_descriptors_v1 *remote,
585  *                                 int iovcnt,
586  *                                 const struct iovec *iov)
587  *
588  * Reads from the remote buffer.
589  */
590 #ifndef __KERNEL__
591 static inline ssize_t smbdirect_rdma_v1_readv(int sockfd,
592                                 const struct smbdirect_buffer_descriptors_v1 __user *remote,
593                                 int iovcnt,
594                                 struct iovec __user *iov)
595 {
596         struct smbdirect_cmsg_buffer cbuffer;
597         struct msghdr msg = {
598                 .msg_iovlen = iovcnt,
599                 .msg_iov = iov,
600         };
601         int msg_flags = 0;
602
603         smbdirect_buffer_remote_read_cmsg_prepare(&msg, &msg_flags, &cbuffer, -1, remote);
604
605         return recvmsg(sockfd, &msg, msg_flags);
606 }
607 #endif /* !__KERNEL__ */
608
609 #ifdef __KERNEL__
610 ssize_t smbdirect_kern_rdma_v1_readv(struct socket *sock,
611                                      const struct smbdirect_buffer_descriptors_v1 *remote,
612                                      size_t size,
613                                      struct iov_iter *iter);
614 #endif /* __KERNEL__ */
615
616 #endif /*  SMBDIRECT_H */