~ubuntu-branches/ubuntu/saucy/lvm2/saucy

« back to all changes in this revision

Viewing changes to libdaemon/server/daemon-server.c

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-05-30 11:02:10 UTC
  • mfrom: (3.1.28 sid)
  • Revision ID: package-import@ubuntu.com-20130530110210-q8bou4f333ruwhn0
Tags: 2.02.98-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - debian/patches/avoid-dev-block.patch: Prefer any other device name over
    names in /dev/block/ since lvm.conf won't handle this.
  - debian/rules:
    - copy .po file to .pot file for Rosetta (Ubuntu specific).
  - debian/{dmsetup,lvm2}-udeb.install:
    - install initramfs and udev hooks in udebs (Debian bug 504341).
  - auto-start VGs as their PVs are discovered (Ubuntu specific):
    - add debian/tree/lvm2/lib/udev/rules.d/85-lvm2.rules: use watershed plus
      the sledgehammer of vgscan/vgchange to turn on VGs as they come online.
    - debian/tree/lvm2/usr/share/initramfs-tools/scripts/hooks/lvm2:
      - add 85-lvm2.rules to the list of udev rules to copy.
      - depend on udev.
    - debian/control:
      - add versioned Depend on watershed in lvm2 for udev rules.
      - add Depends on watershed-udeb in lvm2-udeb for udev rules.
      - add versioned Depend/Breaks on udev in dmsetup for udev rules.
      - add Depend on initramfs-tools in dmsetup so system is not potentially
        rendered unbootable by out-of-order dpkg configuration.
      - In libdevmapper-event1.02.1 add Breaks: dmeventd
        (<< 2.02.95-4ubuntu1) due to debian symbol rename
    - debian/rules:
      - do not install local-top scripts since Ubuntu mounts root using udev.
      - do not install init scripts for lvm2, since udev starts LVM.
      - continue to build clvm support.
    - debian/lvm2.postinst: handle missing lvm2 init script.
    - debian/tree/dmsetup/lib/udev/rules.d/60-persistent-storage-dm.rules:
      watch dm devices for changes with inotify
  - add mountroot failure hooks to help fix bad boots (Debian bug 468115):
    - debian/tree/lvm2/usr/share/initramfs-tools/scripts/init-premount/lvm2
  - remaining changes to upstream event manager packages (Debian bug 514706):
    - debian/rules:
      - enable dmeventd during configure.
    - debian/dmeventd.{8,manpages}: install dmeventd files.
  - rename debian/clvm.defaults to debian/clvm.default so it is installed
    correctly.
  - debian/control: add dmsetup-udeb to libdevmapper1.02.1-udeb recommends.
  - debian/rules: make sure dmsetup and lvm2 initramfs-tools scripts are
    executable.  When the Ubuntu-specific ones are added with a patch,
    they may lose their executable bit.
  - Add and install clvmd resource agent
  - Add dependency on libudev-dev to libdevmapper-dev so that the .pc file
    works.
  - debian/{clvmd.ra,clvm.init}:
    - create /run/lvm if it doesn't exist.
  - debian/clvm.init:
    - exit 3 if not running on status action.
  - Call dh_installman so that our dmeventd manpage actually gets installed
  - Install the missing fsadm manpage.
  - Complete libdevmapper-dev multiarch:
    - move .so symlinks and pkgconfig files to multiarched locations.
    - mark libdevmapper-dev M-A: same

* Dropped changes, applied upstream:
  - Update Micron PCIe SSD and other device-types to latest available.
  - Cherry pick from upstream, remove unsupported udev_get_dev_path() call.
  - Move thin check to global section.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
11
11
 */
12
12
 
13
 
#include "daemon-shared.h"
 
13
#include "daemon-io.h"
 
14
#include "config-util.h"
14
15
#include "daemon-server.h"
 
16
#include "daemon-log.h"
15
17
 
16
18
#include <dlfcn.h>
17
19
#include <errno.h>
26
28
#include <unistd.h>
27
29
#include <signal.h>
28
30
 
29
 
#include <syslog.h>
 
31
#include <syslog.h> /* FIXME. For the global closelog(). */
30
32
 
31
33
#if 0
32
34
/* Create a device monitoring thread. */
69
71
#  define OOM_SCORE_ADJ_MIN (-1000)
70
72
 
71
73
/* Systemd on-demand activation support */
 
74
#  define SD_ACTIVATION_ENV_VAR_NAME "SD_ACTIVATION"
72
75
#  define SD_LISTEN_PID_ENV_VAR_NAME "LISTEN_PID"
73
76
#  define SD_LISTEN_FDS_ENV_VAR_NAME "LISTEN_FDS"
74
77
#  define SD_LISTEN_FDS_START 3
128
131
static int _handle_preloaded_socket(int fd, const char *path)
129
132
{
130
133
        struct stat st_fd;
131
 
        union sockaddr_union sockaddr;
 
134
        union sockaddr_union sockaddr = { .sa.sa_family = 0 };
132
135
        int type = 0;
133
136
        socklen_t len = sizeof(type);
134
137
        size_t path_len = strlen(path);
143
146
            len != sizeof(type) || type != SOCK_STREAM)
144
147
                return 0;
145
148
 
146
 
        memset(&sockaddr, 0, sizeof(sockaddr));
147
149
        len = sizeof(sockaddr);
148
150
        if (getsockname(fd, &sockaddr.sa, &len) < 0 ||
149
151
            len < sizeof(sa_family_t) ||
164
166
        unsigned long env_pid, env_listen_fds;
165
167
        int r = 0;
166
168
 
 
169
        /* SD_ACTIVATION must be set! */
 
170
        if (!(e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) || strcmp(e, "1"))
 
171
                goto out;
 
172
 
167
173
        /* LISTEN_PID must be equal to our PID! */
168
174
        if (!(e = getenv(SD_LISTEN_PID_ENV_VAR_NAME)))
169
175
                goto out;
172
178
        env_pid = strtoul(e, &p, 10);
173
179
        if (errno || !p || *p || env_pid <= 0 ||
174
180
            getpid() != (pid_t) env_pid)
175
 
                ;
 
181
                goto out;
176
182
 
177
183
        /* LISTEN_FDS must be 1 and the fd must be a socket! */
178
184
        if (!(e = getenv(SD_LISTEN_FDS_ENV_VAR_NAME)))
188
194
                ds->socket_fd = SD_FD_SOCKET_SERVER;
189
195
 
190
196
out:
 
197
        unsetenv(SD_ACTIVATION_ENV_VAR_NAME);
191
198
        unsetenv(SD_LISTEN_PID_ENV_VAR_NAME);
192
199
        unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
193
200
        return r;
198
205
static int _open_socket(daemon_state s)
199
206
{
200
207
        int fd = -1;
201
 
        struct sockaddr_un sockaddr;
 
208
        struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
202
209
        mode_t old_mask;
203
210
 
204
211
        (void) dm_prepare_selinux_context(s.socket_path, S_IFSOCK);
214
221
        /* Set Close-on-exec & non-blocking */
215
222
        if (fcntl(fd, F_SETFD, 1))
216
223
                fprintf(stderr, "setting CLOEXEC on socket fd %d failed: %s\n", fd, strerror(errno));
217
 
        fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
 
224
        if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK))
 
225
                fprintf(stderr, "setting O_NONBLOCK on socket fd %d failed: %s\n", fd, strerror(errno));
218
226
 
219
227
        fprintf(stderr, "[D] creating %s\n", s.socket_path);
220
 
        memset(&sockaddr, 0, sizeof(sockaddr));
221
 
        strcpy(sockaddr.sun_path, s.socket_path);
222
 
        sockaddr.sun_family = AF_UNIX;
 
228
        if (!dm_strncpy(sockaddr.sun_path, s.socket_path, sizeof(sockaddr.sun_path))) {
 
229
                fprintf(stderr, "%s: daemon socket path too long.\n", s.socket_path);
 
230
                goto error;
 
231
        }
223
232
 
224
233
        if (bind(fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
225
234
                perror("can't bind local socket.");
324
333
 
325
334
        va_start(ap, id);
326
335
 
327
 
        if (!(res.buffer = format_buffer("response", id, ap)))
328
 
                res.error = ENOMEM;
 
336
        buffer_init(&res.buffer);
 
337
        if (!buffer_append_f(&res.buffer, "response = %s", id, NULL)) {
 
338
                res.error = ENOMEM;
 
339
                goto end;
 
340
        }
 
341
        if (!buffer_append_vf(&res.buffer, ap)) {
 
342
                res.error = ENOMEM;
 
343
                goto end;
 
344
        }
329
345
 
 
346
end:
330
347
        va_end(ap);
331
 
 
332
348
        return res;
333
349
}
334
350
 
337
353
        client_handle client;
338
354
};
339
355
 
340
 
static int buffer_rewrite(char **buf, const char *format, const char *string) {
341
 
        char *old = *buf;
342
 
        int r = dm_asprintf(buf, format, *buf, string);
343
 
 
344
 
        dm_free(old);
345
 
 
346
 
        return (r < 0) ? 0 : 1;
347
 
}
348
 
 
349
 
static int buffer_line(const char *line, void *baton) {
350
 
        response *r = baton;
351
 
 
352
 
        if (r->buffer) {
353
 
                if (!buffer_rewrite(&r->buffer, "%s\n%s", line))
354
 
                        return 0;
355
 
        } else if (dm_asprintf(&r->buffer, "%s\n", line) < 0)
356
 
                return 0;
357
 
 
358
 
        return 1;
359
 
}
360
 
 
361
356
static response builtin_handler(daemon_state s, client_handle h, request r)
362
357
{
363
358
        const char *rq = daemon_request_str(r, "request", "NONE");
 
359
        response res = { .error = EPROTO };
364
360
 
365
361
        if (!strcmp(rq, "hello")) {
366
362
                return daemon_reply_simple("OK", "protocol = %s", s.protocol ?: "default",
367
 
                                           "version = %d", s.protocol_version, NULL);
 
363
                                           "version = %" PRId64, (int64_t) s.protocol_version, NULL);
368
364
        }
369
365
 
370
 
        response res = { .buffer = NULL, .error = EPROTO };
 
366
        buffer_init(&res.buffer);
371
367
        return res;
372
368
}
373
369
 
377
373
        request req;
378
374
        response res;
379
375
 
 
376
        buffer_init(&req.buffer);
 
377
 
380
378
        while (1) {
381
 
                if (!read_buffer(b->client.socket_fd, &req.buffer))
 
379
                if (!buffer_read(b->client.socket_fd, &req.buffer))
382
380
                        goto fail;
383
381
 
384
 
                req.cft = dm_config_from_string(req.buffer);
 
382
                req.cft = dm_config_from_string(req.buffer.mem);
 
383
 
385
384
                if (!req.cft)
386
 
                        fprintf(stderr, "error parsing request:\n %s\n", req.buffer);
 
385
                        fprintf(stderr, "error parsing request:\n %s\n", req.buffer.mem);
 
386
                else
 
387
                        daemon_log_cft(b->s.log, DAEMON_LOG_WIRE, "<- ", req.cft->root);
387
388
 
388
389
                res = builtin_handler(b->s, b->client, req);
389
390
 
390
391
                if (res.error == EPROTO) /* Not a builtin, delegate to the custom handler. */
391
392
                        res = b->s.handler(b->s, b->client, req);
392
393
 
393
 
                if (!res.buffer) {
394
 
                        dm_config_write_node(res.cft->root, buffer_line, &res);
395
 
                        if (!buffer_rewrite(&res.buffer, "%s\n\n", NULL))
 
394
                if (!res.buffer.mem) {
 
395
                        dm_config_write_node(res.cft->root, buffer_line, &res.buffer);
 
396
                        if (!buffer_append(&res.buffer, "\n\n"))
396
397
                                goto fail;
397
398
                        dm_config_destroy(res.cft);
398
399
                }
399
400
 
400
401
                if (req.cft)
401
402
                        dm_config_destroy(req.cft);
402
 
                dm_free(req.buffer);
403
 
 
404
 
                write_buffer(b->client.socket_fd, res.buffer, strlen(res.buffer));
405
 
 
406
 
                free(res.buffer);
 
403
                buffer_destroy(&req.buffer);
 
404
 
 
405
                daemon_log_multi(b->s.log, DAEMON_LOG_WIRE, "-> ", res.buffer.mem);
 
406
                buffer_write(b->client.socket_fd, &res.buffer);
 
407
 
 
408
                buffer_destroy(&res.buffer);
407
409
        }
408
410
fail:
409
411
        /* TODO what should we really do here? */
410
412
        if (close(b->client.socket_fd))
411
413
                perror("close");
412
 
        free(baton);
 
414
        buffer_destroy(&req.buffer);
 
415
        dm_free(baton);
413
416
        return NULL;
414
417
}
415
418
 
441
444
void daemon_start(daemon_state s)
442
445
{
443
446
        int failed = 0;
 
447
        log_state _log = { { 0 } };
 
448
 
444
449
        /*
445
450
         * Switch to C locale to avoid reading large locale-archive file used by
446
451
         * some glibc (on some distributions it takes over 100MB). Some daemons
456
461
        if (!s.foreground)
457
462
                _daemonise();
458
463
 
459
 
        /* TODO logging interface should be somewhat more elaborate */
460
 
        openlog(s.name, LOG_PID, LOG_DAEMON);
461
 
 
462
 
        (void) dm_prepare_selinux_context(s.pidfile, S_IFREG);
463
 
 
464
 
        /*
465
 
         * NB. Take care to not keep stale locks around. Best not exit(...)
466
 
         * after this point.
467
 
         */
468
 
        if (dm_create_lockfile(s.pidfile) == 0)
469
 
                exit(1);
470
 
 
471
 
        (void) dm_prepare_selinux_context(NULL, 0);
 
464
        s.log = &_log;
 
465
        s.log->name = s.name;
 
466
 
 
467
        /* Log important things to syslog by default. */
 
468
        daemon_log_enable(s.log, DAEMON_LOG_OUTLET_SYSLOG, DAEMON_LOG_FATAL, 1);
 
469
        daemon_log_enable(s.log, DAEMON_LOG_OUTLET_SYSLOG, DAEMON_LOG_ERROR, 1);
 
470
 
 
471
        if (s.pidfile) {
 
472
                (void) dm_prepare_selinux_context(s.pidfile, S_IFREG);
 
473
 
 
474
                /*
 
475
                 * NB. Take care to not keep stale locks around. Best not exit(...)
 
476
                 * after this point.
 
477
                 */
 
478
                if (dm_create_lockfile(s.pidfile) == 0)
 
479
                        exit(1);
 
480
 
 
481
                (void) dm_prepare_selinux_context(NULL, 0);
 
482
        }
472
483
 
473
484
        /* Set normal exit signals to request shutdown instead of dying. */
474
485
        signal(SIGINT, &_exit_handler);
481
492
#ifdef linux
482
493
        /* Systemd has adjusted oom killer for us already */
483
494
        if (s.avoid_oom && !_systemd_activation && !_protect_against_oom_killer())
484
 
                syslog(LOG_ERR, "Failed to protect against OOM killer");
 
495
                ERROR(&s, "Failed to protect against OOM killer");
485
496
#endif
486
497
 
487
498
        if (!_systemd_activation && s.socket_path) {
495
506
                kill(getppid(), SIGTERM);
496
507
 
497
508
        if (s.daemon_init)
498
 
                s.daemon_init(&s);
 
509
                if (!s.daemon_init(&s))
 
510
                        failed = 1;
499
511
 
500
512
        while (!_shutdown_requested && !failed) {
501
513
                fd_set in;
504
516
                if (select(FD_SETSIZE, &in, NULL, NULL, NULL) < 0 && errno != EINTR)
505
517
                        perror("select error");
506
518
                if (FD_ISSET(s.socket_fd, &in))
507
 
                        if (!handle_connect(s))
508
 
                                syslog(LOG_ERR, "Failed to handle a client connection.");
 
519
                        if (!_shutdown_requested && !handle_connect(s))
 
520
                                ERROR(&s, "Failed to handle a client connection.");
509
521
        }
510
522
 
511
 
        if (s.socket_fd >= 0)
 
523
        /* If activated by systemd, do not unlink the socket - systemd takes care of that! */
 
524
        if (!_systemd_activation && s.socket_fd >= 0)
512
525
                if (unlink(s.socket_path))
513
526
                        perror("unlink error");
514
527
 
515
528
        if (s.daemon_fini)
516
 
                s.daemon_fini(&s);
517
 
 
518
 
        syslog(LOG_NOTICE, "%s shutting down", s.name);
519
 
        closelog();
520
 
        remove_lockfile(s.pidfile);
 
529
                if (!s.daemon_fini(&s))
 
530
                        failed = 1;
 
531
 
 
532
        INFO(&s, "%s shutting down", s.name);
 
533
 
 
534
        closelog(); /* FIXME */
 
535
        if (s.pidfile)
 
536
                remove_lockfile(s.pidfile);
521
537
        if (failed)
522
538
                exit(1);
523
539
}