Initial Linux ZFS GIT Repo
[zfs.git] / zfs / lib / libdmu-ctl / dctl_server.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26
27 #include <stdio.h>
28 #include <stddef.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <signal.h>
32 #include <limits.h>
33 #include <errno.h>
34 #include <poll.h>
35 #include <pthread.h>
36 #include <unistd.h>
37 #include <sys/debug.h>
38 #include <sys/socket.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/un.h>
42 #include <sys/list.h>
43 #include <sys/cred.h>
44
45 #include <sys/dmu_ctl.h>
46 #include <sys/dmu_ctl_impl.h>
47
48 static dctl_sock_info_t ctl_sock = {
49         .dsi_mtx = PTHREAD_MUTEX_INITIALIZER,
50         .dsi_fd = -1
51 };
52
53 static int dctl_create_socket_common();
54
55 /*
56  * Routines from zfs_ioctl.c
57  */
58 extern int zfs_ioctl_init();
59 extern int zfs_ioctl_fini();
60 extern int zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr,
61     int *rvalp);
62
63 /*
64  * We can't simply put the client file descriptor in wthr_info_t because we
65  * have no way of accessing it from the DMU code without extensive
66  * modifications.
67  *
68  * Therefore each worker thread will have it's own global thread-specific
69  * client_fd variable.
70  */
71 static __thread int client_fd = -1;
72
73 int dctls_copyin(const void *src, void *dest, size_t size)
74 {
75         dctl_cmd_t cmd;
76
77         VERIFY(client_fd >= 0);
78
79         cmd.dcmd_msg = DCTL_COPYIN;
80         cmd.u.dcmd_copy.ptr = (uintptr_t) src;
81         cmd.u.dcmd_copy.size = size;
82
83         if (dctl_send_msg(client_fd, &cmd) != 0)
84                 return EFAULT;
85
86         if (dctl_read_data(client_fd, dest, size) != 0)
87                 return EFAULT;
88
89         return 0;
90 }
91
92 int dctls_copyinstr(const char *from, char *to, size_t max, size_t *len)
93 {
94         dctl_cmd_t msg;
95         size_t copied;
96
97         VERIFY(client_fd >= 0);
98
99         if (max == 0)
100                 return ENAMETOOLONG;
101         if (max < 0)
102                 return EFAULT;
103
104         msg.dcmd_msg = DCTL_COPYINSTR;
105         msg.u.dcmd_copy.ptr = (uintptr_t) from;
106         msg.u.dcmd_copy.size = max;
107
108         if (dctl_send_msg(client_fd, &msg) != 0)
109                 return EFAULT;
110
111         if (dctl_read_msg(client_fd, &msg) != 0)
112                 return EFAULT;
113
114         if (msg.dcmd_msg != DCTL_GEN_REPLY)
115                 return EFAULT;
116
117         copied = msg.u.dcmd_reply.size;
118
119         if (copied >= max)
120                 return EFAULT;
121
122         if (copied > 0)
123                 if (dctl_read_data(client_fd, to, copied) != 0)
124                         return EFAULT;
125
126         to[copied] = '\0';
127
128         if (len != NULL)
129                 *len = copied + 1;
130
131         return msg.u.dcmd_reply.rc;
132 }
133
134 int dctls_copyout(const void *src, void *dest, size_t size)
135 {
136         dctl_cmd_t cmd;
137
138         VERIFY(client_fd >= 0);
139
140         cmd.dcmd_msg = DCTL_COPYOUT;
141         cmd.u.dcmd_copy.ptr = (uintptr_t) dest;
142         cmd.u.dcmd_copy.size = size;
143
144         if (dctl_send_msg(client_fd, &cmd) != 0)
145                 return EFAULT;
146
147         if (dctl_send_data(client_fd, src, size) != 0)
148                 return EFAULT;
149
150         return 0;
151 }
152
153 int dctls_fd_read(int fd, void *buf, ssize_t len, ssize_t *residp)
154 {
155         dctl_cmd_t msg;
156         uint64_t dsize;
157         int error;
158
159         VERIFY(client_fd >= 0);
160
161         msg.dcmd_msg = DCTL_FD_READ;
162         msg.u.dcmd_fd_io.fd = fd;
163         msg.u.dcmd_fd_io.size = len;
164
165         if ((error = dctl_send_msg(client_fd, &msg)) != 0)
166                 return error;
167
168         if ((error = dctl_read_msg(client_fd, &msg)) != 0)
169                 return error;
170
171         if (msg.dcmd_msg != DCTL_GEN_REPLY)
172                 return EIO;
173
174         if (msg.u.dcmd_reply.rc != 0)
175                 return msg.u.dcmd_reply.rc;
176
177         dsize = msg.u.dcmd_reply.size;
178
179         if (dsize > 0)
180                 error = dctl_read_data(client_fd, buf, dsize);
181
182         *residp = len - dsize;
183
184         return error;
185 }
186
187 int dctls_fd_write(int fd, const void *src, ssize_t len)
188 {
189         dctl_cmd_t msg;
190         int error;
191
192         VERIFY(client_fd >= 0);
193
194         msg.dcmd_msg = DCTL_FD_WRITE;
195         msg.u.dcmd_fd_io.fd = fd;
196         msg.u.dcmd_fd_io.size = len;
197
198         error = dctl_send_msg(client_fd, &msg);
199
200         if (!error)
201                 error = dctl_send_data(client_fd, src, len);
202
203         if (!error)
204                 error = dctl_read_msg(client_fd, &msg);
205
206         if (error)
207                 return error;
208
209         if (msg.dcmd_msg != DCTL_GEN_REPLY)
210                 return EIO;
211
212         if (msg.u.dcmd_reply.rc != 0)
213                 return msg.u.dcmd_reply.rc;
214
215         /*
216          * We have to do this because the original upstream code
217          * does not check if residp == len.
218          */
219         if (msg.u.dcmd_reply.size != len)
220                 return EIO;
221
222         return 0;
223 }
224
225 /* Handle a new connection */
226 static void dctl_handle_conn(int sock_fd)
227 {
228         dctl_cmd_t cmd;
229         dev_t dev = { 0 };
230         int rc;
231
232         client_fd = sock_fd;
233
234         while (dctl_read_msg(sock_fd, &cmd) == 0) {
235                 if (cmd.dcmd_msg != DCTL_IOCTL) {
236                         fprintf(stderr, "%s(): unexpected message type.\n",
237                             __func__);
238                         break;
239                 }
240
241                 rc = zfsdev_ioctl(dev, cmd.u.dcmd_ioctl.cmd,
242                     (intptr_t) cmd.u.dcmd_ioctl.arg, 0, NULL, NULL);
243
244                 cmd.dcmd_msg = DCTL_IOCTL_REPLY;
245                 cmd.u.dcmd_reply.rc = rc;
246
247                 if (dctl_send_msg(sock_fd, &cmd) != 0)
248                         break;
249         }
250         close(sock_fd);
251
252         client_fd = -1;
253 }
254
255 /* Main worker thread loop */
256 static void *dctl_thread(void *arg)
257 {
258         wthr_info_t *thr = arg;
259         struct pollfd fds[1];
260
261         fds[0].events = POLLIN;
262
263         pthread_mutex_lock(&ctl_sock.dsi_mtx);
264
265         while (!thr->wthr_exit) {
266                 /* Clean-up dead threads */
267                 dctl_thr_join();
268
269                 /* The file descriptor might change in the thread lifetime */
270                 fds[0].fd = ctl_sock.dsi_fd;
271
272                 /* Poll socket with 1-second timeout */
273                 int rc = poll(fds, 1, 1000);
274                 if (rc == 0 || (rc == -1 && errno == EINTR))
275                         continue;
276
277                 /* Recheck the exit flag */
278                 if (thr->wthr_exit)
279                         break;
280
281                 if (rc == -1) {
282                         /* Unknown error, let's try to recreate the socket */
283                         close(ctl_sock.dsi_fd);
284                         ctl_sock.dsi_fd = -1;
285
286                         if (dctl_create_socket_common() != 0)
287                                 break;
288
289                         continue;
290                 }
291                 ASSERT(rc == 1);
292
293                 short rev = fds[0].revents;
294                 if (rev == 0)
295                         continue;
296                 ASSERT(rev == POLLIN);
297
298                 /*
299                  * At this point there should be a connection ready to be
300                  * accepted.
301                  */
302                 int client_fd = accept(ctl_sock.dsi_fd, NULL, NULL);
303                 /* Many possible errors here, we'll just retry */
304                 if (client_fd == -1)
305                         continue;
306
307                 /*
308                  * Now lets handle the request. This can take a very
309                  * long time (hours even), so we'll let other threads
310                  * handle new connections.
311                  */
312                 pthread_mutex_unlock(&ctl_sock.dsi_mtx);
313
314                 dctl_thr_rebalance(thr, B_FALSE);
315                 dctl_handle_conn(client_fd);
316                 dctl_thr_rebalance(thr, B_TRUE);
317
318                 pthread_mutex_lock(&ctl_sock.dsi_mtx);
319         }
320         pthread_mutex_unlock(&ctl_sock.dsi_mtx);
321
322         dctl_thr_die(thr);
323
324         return NULL;
325 }
326
327 static int dctl_create_socket_common()
328 {
329         dctl_sock_info_t *s = &ctl_sock;
330         size_t size;
331         int error;
332
333         ASSERT(s->dsi_fd == -1);
334
335         /*
336          * Unlink old socket, in case it exists.
337          * We don't care about errors here.
338          */
339         unlink(s->dsi_path);
340
341         /* Create the socket */
342         s->dsi_fd = socket(PF_UNIX, SOCK_STREAM, 0);
343         if (s->dsi_fd == -1) {
344                 error = errno;
345                 perror("socket");
346                 return error;
347         }
348
349         s->dsi_addr.sun_family = AF_UNIX;
350
351         size = sizeof(s->dsi_addr.sun_path) - 1;
352         strncpy(s->dsi_addr.sun_path, s->dsi_path, size);
353
354         s->dsi_addr.sun_path[size] = '\0';
355
356         if (bind(s->dsi_fd, (struct sockaddr *) &s->dsi_addr,
357             sizeof(s->dsi_addr)) != 0) {
358                 error = errno;
359                 perror("bind");
360                 return error;
361         }
362
363         if (listen(s->dsi_fd, LISTEN_BACKLOG) != 0) {
364                 error = errno;
365                 perror("listen");
366                 unlink(s->dsi_path);
367                 return error;
368         }
369
370         return 0;
371 }
372
373 static int dctl_create_socket(const char *cfg_dir)
374 {
375         int error;
376         dctl_sock_info_t *s = &ctl_sock;
377
378         ASSERT(s->dsi_path == NULL);
379         ASSERT(s->dsi_fd == -1);
380
381         int pathsize = strlen(cfg_dir) + strlen(SOCKNAME) + 2;
382         if (pathsize > sizeof(s->dsi_addr.sun_path))
383                 return ENAMETOOLONG;
384
385         s->dsi_path = malloc(pathsize);
386         if (s->dsi_path == NULL)
387                 return ENOMEM;
388
389         strcpy(s->dsi_path, cfg_dir);
390         strcat(s->dsi_path, "/" SOCKNAME);
391
392         /*
393          * For convenience, create the directory in case it doesn't exist.
394          * We don't care about errors here.
395          */
396         mkdir(cfg_dir, 0770);
397
398         error = dctl_create_socket_common();
399
400         if (error) {
401                 free(s->dsi_path);
402
403                 if (s->dsi_fd != -1) {
404                         close(s->dsi_fd);
405                         s->dsi_fd = -1;
406                 }
407         }
408
409         return error;
410 }
411
412 static void dctl_destroy_socket()
413 {
414         dctl_sock_info_t *s = &ctl_sock;
415
416         ASSERT(s->dsi_path != NULL);
417         ASSERT(s->dsi_fd != -1);
418
419         close(s->dsi_fd);
420         s->dsi_fd = -1;
421
422         unlink(s->dsi_path);
423         free(s->dsi_path);
424 }
425
426 /*
427  * Initialize the DMU userspace control interface.
428  * This should be called after kernel_init().
429  *
430  * Note that only very rarely we have more than a couple of simultaneous
431  * lzfs/lzpool connections. Since the thread pool grows automatically when all
432  * threads are busy, a good value for min_thr and max_free_thr is 2.
433  */
434 int dctl_server_init(const char *cfg_dir, int min_thr, int max_free_thr)
435 {
436         int error;
437
438         ASSERT(min_thr > 0);
439         ASSERT(max_free_thr >= min_thr);
440
441         error = zfs_ioctl_init();
442         if (error)
443                 return error;
444
445         error = dctl_create_socket(cfg_dir);
446         if (error) {
447                 (void) zfs_ioctl_fini();
448                 return error;
449         }
450
451         error = dctl_thr_pool_create(min_thr, max_free_thr, dctl_thread);
452         if (error) {
453                 (void) zfs_ioctl_fini();
454                 dctl_destroy_socket();
455                 return error;
456         }
457
458         return 0;
459 }
460
461 /*
462  * Terminate control interface.
463  * This should be called after closing all objsets, but before calling
464  * kernel_fini().
465  * May return EBUSY if the SPA is busy.
466  *
467  * Thread pool destruction can take a while due to poll()
468  * timeout or due to a thread being busy (e.g. a backup is being taken).
469  */
470 int dctl_server_fini()
471 {
472         dctl_thr_pool_stop();
473         dctl_destroy_socket();
474
475         return zfs_ioctl_fini();
476 }