]>
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>
34 static const __u32 start_magic
= 0x5a5aa5a5;
35 static const __u32 end_magic
= 0xa5a55a5a;
37 static int send_buf(int fd
, const void* buf
, int len
, int tmo
)
41 struct timeval timeout
= {tmo
, 0};
42 struct timeval
*ptmo
= tmo
? &timeout
: NULL
;
47 rv
= select(fd
+1, NULL
, &set
, NULL
, ptmo
);
50 rv
= write(fd
, buf
, len
);
59 static int recv_buf(int fd
, void* buf
, int len
, int tmo
)
63 struct timeval timeout
= {tmo
, 0};
64 struct timeval
*ptmo
= tmo
? &timeout
: NULL
;
69 rv
= select(fd
+1, &set
, NULL
, NULL
, ptmo
);
72 rv
= read(fd
, buf
, len
);
82 int send_message(int fd
, struct metadata_update
*msg
, int tmo
)
87 rv
= send_buf(fd
, &start_magic
, 4, tmo
);
88 rv
= rv
?: send_buf(fd
, &len
, 4, tmo
);
90 rv
= rv
?: send_buf(fd
, msg
->buf
, msg
->len
, tmo
);
91 rv
= send_buf(fd
, &end_magic
, 4, tmo
);
96 int receive_message(int fd
, struct metadata_update
*msg
, int tmo
)
102 rv
= recv_buf(fd
, &magic
, 4, tmo
);
103 if (rv
< 0 || magic
!= start_magic
)
105 rv
= recv_buf(fd
, &len
, 4, tmo
);
106 if (rv
< 0 || len
> MSG_MAX_LEN
)
109 msg
->buf
= malloc(len
);
110 if (msg
->buf
== NULL
)
112 rv
= recv_buf(fd
, msg
->buf
, len
, tmo
);
119 rv
= recv_buf(fd
, &magic
, 4, tmo
);
120 if (rv
< 0 || magic
!= end_magic
) {
128 int ack(int fd
, int tmo
)
130 struct metadata_update msg
= { .len
= 0 };
132 return send_message(fd
, &msg
, tmo
);
135 int wait_reply(int fd
, int tmo
)
137 struct metadata_update msg
;
138 return receive_message(fd
, &msg
, tmo
);
141 int connect_monitor(char *devname
)
146 struct sockaddr_un addr
;
150 pos
= sprintf(path
, "%s/", MDMON_DIR
);
151 if (is_subarray(devname
)) {
153 c
= strchr(devname
, '/');
156 snprintf(&path
[pos
], c
- devname
+ 1, "%s", devname
);
159 pos
+= sprintf(&path
[pos
], "%s", devname
);
160 sprintf(&path
[pos
], ".sock");
162 sfd
= socket(PF_LOCAL
, SOCK_STREAM
, 0);
166 addr
.sun_family
= PF_LOCAL
;
167 strcpy(addr
.sun_path
, path
);
168 if (connect(sfd
, &addr
, sizeof(addr
)) < 0) {
173 fl
= fcntl(sfd
, F_GETFL
, 0);
175 fcntl(sfd
, F_SETFL
, fl
);
180 int fping_monitor(int sfd
)
187 /* try to ping existing socket */
188 if (ack(sfd
, 20) != 0)
191 /* check the reply */
192 if (!err
&& wait_reply(sfd
, 20) != 0)
199 /* give the monitor a chance to update the metadata */
200 int ping_monitor(char *devname
)
202 int sfd
= connect_monitor(devname
);
203 int err
= fping_monitor(sfd
);
209 /* give the manager a chance to view the updated container state. This
210 * would naturally happen due to the manager noticing a change in
211 * /proc/mdstat; however, pinging encourages this detection to happen
212 * while an exclusive open() on the container is active
214 int ping_manager(char *devname
)
216 int sfd
= connect_monitor(devname
);
217 struct metadata_update msg
= { .len
= -1 };
223 err
= send_message(sfd
, &msg
, 20);
225 /* check the reply */
226 if (!err
&& wait_reply(sfd
, 20) != 0)