~ubuntu-branches/ubuntu/quantal/lxc/quantal-201208301614

« back to all changes in this revision

Viewing changes to src/lxc/monitor.c

  • Committer: Bazaar Package Importer
  • Author(s): Guido Trotter
  • Date: 2009-04-29 17:49:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090429174913-jvahs1ykizqtodje
Tags: upstream-0.6.2
ImportĀ upstreamĀ versionĀ 0.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * lxc: linux Container library
 
3
 *
 
4
 * (C) Copyright IBM Corp. 2007, 2008
 
5
 *
 
6
 * Authors:
 
7
 * Daniel Lezcano <dlezcano at fr.ibm.com>
 
8
 *
 
9
 * This library is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU Lesser General Public
 
11
 * License as published by the Free Software Foundation; either
 
12
 * version 2.1 of the License, or (at your option) any later version.
 
13
 *
 
14
 * This library is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
 * Lesser General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU Lesser General Public
 
20
 * License along with this library; if not, write to the Free Software
 
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
22
 */
 
23
#include <stdio.h>
 
24
#include <errno.h>
 
25
#include <unistd.h>
 
26
#include <string.h>
 
27
#include <stdlib.h>
 
28
#include <fcntl.h>
 
29
#include <sys/types.h>
 
30
#include <sys/stat.h>
 
31
#include <sys/param.h>
 
32
#include <sys/inotify.h>
 
33
#include <sys/socket.h>
 
34
#include <netinet/in.h>
 
35
#include <net/if.h>
 
36
#include <linux/netlink.h>
 
37
#include <linux/rtnetlink.h>
 
38
 
 
39
#include "error.h"
 
40
#include <lxc/lxc.h>
 
41
#include <lxc/log.h>
 
42
 
 
43
lxc_log_define(lxc_monitor, lxc);
 
44
 
 
45
#ifndef UNIX_PATH_MAX
 
46
#define UNIX_PATH_MAX 108
 
47
#endif
 
48
 
 
49
#ifndef SOL_NETLINK
 
50
#define SOL_NETLINK 270
 
51
#endif
 
52
 
 
53
/* assuming this multicast group is not used by anyone else :/
 
54
 * otherwise a new genetlink family should be defined to own
 
55
 * its multicast groups */
 
56
#define MONITOR_MCGROUP RTNLGRP_MAX
 
57
 
 
58
int lxc_monitor(const char *name, int output_fd)
 
59
{
 
60
        char path[MAXPATHLEN];
 
61
        int err = -1, nfd, wfd, state;
 
62
 
 
63
        nfd = inotify_init();
 
64
        if (nfd < 0) {
 
65
                SYSERROR("failed to initialize inotify");
 
66
                return -1;
 
67
        }
 
68
 
 
69
        snprintf(path, MAXPATHLEN, LXCPATH "/%s/state", name);
 
70
 
 
71
        wfd = inotify_add_watch(nfd, path, IN_DELETE_SELF|IN_CLOSE_WRITE);
 
72
        if (wfd < 0) {
 
73
                SYSERROR("failed to add a watch on %s", path);
 
74
                goto out;
 
75
        }
 
76
 
 
77
        for(;;) {
 
78
                struct inotify_event evt;
 
79
 
 
80
                if (read(nfd, &evt, sizeof(evt)) < 0) {
 
81
                        SYSERROR("failed to read inotify event");
 
82
                        goto out;
 
83
                }
 
84
 
 
85
                if (evt.mask & IN_CLOSE_WRITE) {
 
86
 
 
87
                        state = lxc_getstate(name);
 
88
                        if (state < 0) {
 
89
                                ERROR("failed to get the state for %s",
 
90
                                              name);
 
91
                                goto out;
 
92
                        }
 
93
 
 
94
                        if (write(output_fd, &state, sizeof(state)) < 0) {
 
95
                                SYSERROR("failed to send state to %d",
 
96
                                                 output_fd);
 
97
                                goto out;
 
98
                        }
 
99
                        continue;
 
100
                }
 
101
 
 
102
                if (evt.mask & IN_DELETE_SELF) {
 
103
                        close(output_fd);
 
104
                        err = 0;
 
105
                        goto out;
 
106
                }
 
107
 
 
108
                ERROR("unknown evt for inotity (%d)", evt.mask);
 
109
                goto out;
 
110
        }
 
111
 
 
112
out:
 
113
        inotify_rm_watch(nfd, wfd);
 
114
        close(nfd);
 
115
        return err;
 
116
}
 
117
 
 
118
static void lxc_monitor_send(struct lxc_msg *msg)
 
119
{
 
120
        int fd;
 
121
        struct sockaddr_nl addr;
 
122
 
 
123
        fd = socket(PF_NETLINK, SOCK_RAW, 0);
 
124
        if (fd < 0) {
 
125
                SYSERROR("failed to create notification socket");
 
126
                return;
 
127
        }
 
128
 
 
129
        memset(&addr, 0, sizeof(addr));
 
130
 
 
131
        addr.nl_family = AF_NETLINK;
 
132
        addr.nl_pid = 0;
 
133
        addr.nl_groups = MONITOR_MCGROUP;
 
134
 
 
135
        sendto(fd, msg, sizeof(*msg), 0,
 
136
               (const struct sockaddr *)&addr, sizeof(addr));
 
137
 
 
138
        close(fd);
 
139
}
 
140
 
 
141
void lxc_monitor_send_state(const char *name, lxc_state_t state)
 
142
{
 
143
        struct lxc_msg msg = { .type = lxc_msg_state,
 
144
                               .value = state };
 
145
        strncpy(msg.name, name, sizeof(msg.name));
 
146
 
 
147
        lxc_monitor_send(&msg);
 
148
}
 
149
 
 
150
int lxc_monitor_open(void)
 
151
{
 
152
        int fd;
 
153
        struct sockaddr_nl addr;
 
154
 
 
155
        fd = socket(PF_NETLINK, SOCK_RAW, 0);
 
156
        if (fd < 0) {
 
157
                SYSERROR("failed to create notification socket");
 
158
                return -LXC_ERROR_INTERNAL;
 
159
        }
 
160
 
 
161
        memset(&addr, 0, sizeof(addr));
 
162
 
 
163
        addr.nl_family = AF_NETLINK;
 
164
        addr.nl_pid = 0;
 
165
        addr.nl_groups = MONITOR_MCGROUP;
 
166
 
 
167
        if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr))) {
 
168
                SYSERROR("failed to bind to multicast group '%d'",
 
169
                        addr.nl_groups);
 
170
                close(fd);
 
171
                return -1;
 
172
        }
 
173
 
 
174
        return fd;
 
175
}
 
176
 
 
177
int lxc_monitor_read(int fd, struct lxc_msg *msg)
 
178
{
 
179
        struct sockaddr_nl from;
 
180
        socklen_t len = sizeof(from);
 
181
        int ret;
 
182
 
 
183
        ret = recvfrom(fd, msg, sizeof(*msg), 0, 
 
184
                       (struct sockaddr *)&from, &len);
 
185
        if (ret < 0) {
 
186
                SYSERROR("failed to received state");
 
187
                return -LXC_ERROR_INTERNAL;
 
188
        }
 
189
 
 
190
        return ret;
 
191
}
 
192
 
 
193
int lxc_monitor_close(int fd)
 
194
{
 
195
        return close(fd);
 
196
}