]>
git.ipfire.org Git - thirdparty/mdadm.git/blob - msg.c
2 * Copyright (C) 2008 Intel Corporation
4 * mdmon socket / message handling
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <sys/types.h>
29 #include <sys/socket.h>
43 const int start_magic
= 0x5a5aa5a5;
44 const int end_magic
= 0xa5a55a5a;
46 #define txrx(fd, buf, size, flags) (recv_send ? \
47 recv(fd, buf, size, flags) : \
48 send(fd, buf, size, flags))
50 /* non-blocking send/receive with n second timeout */
51 static enum tx_rx_state
52 tx_rx_message(int fd
, struct md_message
*msg
, int recv_send
, int tmo
)
54 int d
= recv_send
? 0 : start_magic
;
55 int flags
= recv_send
? 0 : MSG_NOSIGNAL
;
56 enum tx_rx_state state
= TX_RX_START
;
58 size_t size
= sizeof(d
);
65 rc
= txrx(fd
, buf
+ n
, size
- n
, flags
);
66 if (rc
<= 0) { /* error */
67 if (rc
== -1 && errno
== EAGAIN
)
71 } else if (rc
+ n
== size
) /* done */
74 if (recv_send
&& d
!= start_magic
)
79 size
= sizeof(msg
->seq
);
84 state
= TX_RX_NUM_BYTES
;
85 buf
= &msg
->num_bytes
;
86 size
= sizeof(msg
->num_bytes
);
91 sizeof(union md_message_commands
))
93 else if (recv_send
&& msg
->num_bytes
) {
94 msg
->buf
= malloc(msg
->num_bytes
);
100 size
= msg
->num_bytes
;
103 } else if (!recv_send
&& msg
->num_bytes
) {
106 size
= msg
->num_bytes
;
109 d
= recv_send
? 0 : end_magic
;
117 d
= recv_send
? 0 : end_magic
;
124 if (recv_send
&& d
!= end_magic
)
127 state
= TX_RX_SUCCESS
;
138 struct timeval timeout
= { tmo
, 0 };
139 struct timeval
*ptmo
= tmo
? &timeout
: NULL
;
145 rc
= select(fd
+ 1, &set
, NULL
, NULL
, ptmo
);
147 rc
= select(fd
+ 1, NULL
, &set
, NULL
, ptmo
);
152 } while (state
< TX_RX_SUCCESS
);
158 int receive_message(int fd
, struct md_message
*msg
, int tmo
)
160 if (tx_rx_message(fd
, msg
, 1, tmo
) == TX_RX_SUCCESS
)
166 int send_message(int fd
, struct md_message
*msg
, int tmo
)
168 if (tx_rx_message(fd
, msg
, 0, tmo
) == TX_RX_SUCCESS
)
174 int ack(int fd
, int seq
, int tmo
)
176 struct md_message msg
= { .seq
= seq
, .num_bytes
= 0 };
178 return send_message(fd
, &msg
, tmo
);
181 int nack(int fd
, int err
, int tmo
)
183 struct md_message msg
= { .seq
= err
, .num_bytes
= 0 };
185 return send_message(fd
, &msg
, tmo
);
188 int send_remove_device(int fd
, dev_t rdev
, int seq
, int tmo
)
190 struct md_remove_device_cmd cmd
= { .action
= md_action_remove_device
,
193 struct md_message msg
= { .seq
= seq
,
194 .num_bytes
= sizeof(cmd
),
198 return send_message(fd
, &msg
, tmo
);
201 int connect_monitor(char *devname
)
206 struct sockaddr_un addr
;
208 sprintf(path
, "/var/run/mdadm/%s.sock", devname
);
209 sfd
= socket(PF_LOCAL
, SOCK_STREAM
, 0);
213 addr
.sun_family
= PF_LOCAL
;
214 strcpy(addr
.sun_path
, path
);
215 if (connect(sfd
, &addr
, sizeof(addr
)) < 0) {
220 fl
= fcntl(sfd
, F_GETFL
, 0);
222 fcntl(sfd
, F_SETFL
, fl
);
227 int ping_monitor(char *devname
)
229 int sfd
= connect_monitor(devname
);
230 struct md_message msg
;
236 /* try to ping existing socket */
237 if (ack(sfd
, 0, 0) != 0)
240 /* check the reply */
241 if (!err
&& receive_message(sfd
, &msg
, 0) != 0)