Whamcloud - gitweb
LU-19098 hsm: don't print progname twice with lhsmtool
[fs/lustre-release.git] / lustre / utils / liblustreapi_kernelconn.c
1 // SPDX-License-Identifier: LGPL-2.1+
2 /*
3  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
4  * Use is subject to license terms.
5  *
6  * Copyright (c) 2012, 2013, Intel Corporation.
7  */
8 /*
9  * This file is part of Lustre, http://www.lustre.org/
10  *
11  * Author: Nathan Rutman <nathan.rutman@sun.com>
12  *
13  * Kernel <-> userspace communication routines.
14  * Using pipes for all arches.
15  */
16
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <string.h>
20 #include <errno.h>
21
22 #include <lustre/lustreapi.h>
23
24 #include "lustreapi_internal.h"
25
26 /** Start the userspace side of a KUC pipe.
27  * @param link Private descriptor for pipe/socket.
28  * @param groups KUC broadcast group to listen to
29  *          (can be null for unicast to this pid)
30  * @param rfd_flags flags for read side of pipe (e.g. O_NONBLOCK)
31  */
32 int libcfs_ukuc_start(struct lustre_kernelcomm *link,
33                       int group, int rfd_flags)
34 {
35         int pfd[2];
36         int rc;
37
38         link->lk_rfd = link->lk_wfd = LK_NOFD;
39
40         if (pipe(pfd) < 0)
41                 return -errno;
42
43         if (fcntl(pfd[0], F_SETFL, rfd_flags) < 0) {
44                 rc = -errno;
45                 close(pfd[0]);
46                 close(pfd[1]);
47                 return rc;
48         }
49
50         memset(link, 0, sizeof(*link));
51         link->lk_rfd = pfd[0];
52         link->lk_wfd = pfd[1];
53         link->lk_group = group;
54         link->lk_uid = getpid();
55         return 0;
56 }
57
58 int libcfs_ukuc_stop(struct lustre_kernelcomm *link)
59 {
60         int rc;
61
62         if (link->lk_wfd != LK_NOFD)
63                 close(link->lk_wfd);
64         rc = close(link->lk_rfd);
65         link->lk_rfd = link->lk_wfd = LK_NOFD;
66         return rc;
67 }
68
69 /** Returns the file descriptor for the read side of the pipe,
70  *  to be used with poll/select.
71  * @param link Private descriptor for pipe/socket.
72  */
73 int libcfs_ukuc_get_rfd(struct lustre_kernelcomm *link)
74 {
75         return link->lk_rfd;
76 }
77
78 #define lhsz sizeof(*kuch)
79
80 /** Read a message from the link.
81  * Allocates memory, returns handle
82  *
83  * @param link Private descriptor for pipe/socket.
84  * @param buf Buffer to read into, must include size for kuc_hdr
85  * @param maxsize Maximum message size allowed
86  * @param transport Only listen to messages on this transport
87  *      (and the generic transport)
88  */
89 int libcfs_ukuc_msg_get(struct lustre_kernelcomm *link, char *buf, int maxsize,
90                         int transport)
91 {
92         struct kuc_hdr *kuch;
93         int rc = 0;
94
95         memset(buf, 0, maxsize);
96
97         while (1) {
98                 /* Read header first to get message size */
99                 rc = read(link->lk_rfd, buf, lhsz);
100                 if (rc <= 0) {
101                         rc = -errno;
102                         break;
103                 }
104                 kuch = (struct kuc_hdr *)buf;
105
106                 if (kuch->kuc_magic != KUC_MAGIC) {
107                         llapi_err_noerrno(LLAPI_MSG_ERROR,
108                                           "bad message magic %x != %x\n",
109                                           kuch->kuc_magic, KUC_MAGIC);
110                         rc = -EPROTO;
111                         break;
112                 }
113
114                 if (kuch->kuc_msglen > maxsize) {
115                         rc = -EMSGSIZE;
116                         break;
117                 }
118
119                 /* Read payload */
120                 rc = read(link->lk_rfd, buf + lhsz, kuch->kuc_msglen - lhsz);
121                 if (rc < 0) {
122                         rc = -errno;
123                         break;
124                 }
125                 if (rc < (kuch->kuc_msglen - lhsz)) {
126                         llapi_err_noerrno(LLAPI_MSG_ERROR,
127                                           "short read: got %d of %d bytes\n",
128                                           rc, kuch->kuc_msglen);
129                         rc = -EPROTO;
130                         break;
131                 }
132
133                 if (kuch->kuc_transport == transport ||
134                     kuch->kuc_transport == KUC_TRANSPORT_GENERIC) {
135                         return 0;
136                 }
137                 /* Drop messages for other transports */
138         }
139         return rc;
140 }
141