~ubuntu-branches/ubuntu/vivid/lvm2/vivid

« back to all changes in this revision

Viewing changes to daemons/dmeventd/dmeventd.c

  • Committer: Package Import Robot
  • Author(s): Bastian Blank
  • Date: 2012-05-01 20:27:50 UTC
  • mto: (3.1.23 sid)
  • mto: This revision was merged to the branch mainline in revision 72.
  • Revision ID: package-import@ubuntu.com-20120501202750-gljjjtblowwq9mw8
Tags: upstream-2.02.95
ImportĀ upstreamĀ versionĀ 2.02.95

Show diffs side-by-side

added added

removed removed

Lines of Context:
448
448
{
449
449
        struct dm_event_daemon_message *msg = message_data->msg;
450
450
        struct thread_status *thread;
451
 
        int i = 0, j = 0;
 
451
        int i, j;
452
452
        int ret = -1;
453
453
        int count = dm_list_size(&_thread_registry);
454
454
        int size = 0, current = 0;
739
739
                        return;
740
740
                }
741
741
        thread->status = DM_THREAD_DONE;
 
742
        pthread_mutex_lock(&_timeout_mutex);
742
743
        UNLINK_THREAD(thread);
743
744
        LINK(thread, &_thread_registry_unused);
 
745
        pthread_mutex_unlock(&_timeout_mutex);
744
746
        _unlock_mutex();
745
747
}
746
748
 
751
753
        if (!dmt)
752
754
                return NULL;
753
755
 
754
 
        if (!dm_task_set_uuid(dmt, ts->device.uuid))
755
 
                return NULL;
 
756
        if (!dm_task_set_uuid(dmt, ts->device.uuid)) {
 
757
                dm_task_destroy(dmt);
 
758
                return NULL;
 
759
        }
756
760
 
757
761
        if (!dm_task_run(dmt)) {
758
762
                dm_task_destroy(dmt);
996
1000
           almost as good as dead already... */
997
1001
        if (thread_new->events & DM_EVENT_TIMEOUT) {
998
1002
                ret = -_register_for_timeout(thread_new);
999
 
                if (ret) {
1000
 
                    _unlock_mutex();
1001
 
                    goto out;
1002
 
                }
 
1003
                if (ret)
 
1004
                        goto outth;
1003
1005
        }
1004
1006
 
1005
1007
        if (!(thread = _lookup_thread_status(message_data))) {
1025
1027
        /* Or event # into events bitfield. */
1026
1028
        thread->events |= message_data->events.field;
1027
1029
 
 
1030
    outth:
1028
1031
        _unlock_mutex();
1029
1032
 
1030
1033
      out:
1076
1079
         * unlink and terminate its monitoring thread.
1077
1080
         */
1078
1081
        if (!thread->events) {
 
1082
                pthread_mutex_lock(&_timeout_mutex);
1079
1083
                UNLINK_THREAD(thread);
1080
1084
                LINK(thread, &_thread_registry_unused);
 
1085
                pthread_mutex_unlock(&_timeout_mutex);
1081
1086
        }
1082
1087
        _unlock_mutex();
1083
1088
 
1099
1104
        const char *id = message_data->id;
1100
1105
        const char *dso = thread->dso_data->dso_name;
1101
1106
        const char *dev = thread->device.uuid;
 
1107
        int r;
1102
1108
        unsigned events = ((thread->status == DM_THREAD_RUNNING)
1103
1109
                           && (thread->events)) ? thread->events : thread->
1104
1110
            events | DM_EVENT_REGISTRATION_PENDING;
1105
1111
 
1106
1112
        dm_free(msg->data);
1107
1113
 
1108
 
        msg->size = dm_asprintf(&(msg->data), fmt, id, dso, dev, events);
 
1114
        if ((r = dm_asprintf(&(msg->data), fmt, id, dso, dev, events)) < 0) {
 
1115
                msg->size = 0;
 
1116
                return -ENOMEM;
 
1117
        }
1109
1118
 
1110
 
        _unlock_mutex();
 
1119
        msg->size = (uint32_t) r;
1111
1120
 
1112
1121
        return 0;
1113
1122
}
1140
1149
static int _get_registered_dev(struct message_data *message_data, int next)
1141
1150
{
1142
1151
        struct thread_status *thread, *hit = NULL;
 
1152
        int ret = -ENOENT;
1143
1153
 
1144
1154
        _lock_mutex();
1145
1155
 
1156
1166
         * If we got a registered device and want the next one ->
1157
1167
         * fetch next conforming element off the list.
1158
1168
         */
1159
 
        if (hit && !next) {
1160
 
                _unlock_mutex();
1161
 
                return _registered_device(message_data, hit);
1162
 
        }
 
1169
        if (hit && !next)
 
1170
                goto reg;
1163
1171
 
1164
1172
        if (!hit)
1165
1173
                goto out;
1166
1174
 
1167
 
        thread = hit;
1168
 
 
1169
1175
        while (1) {
1170
1176
                if (dm_list_end(&_thread_registry, &thread->list))
1171
1177
                        goto out;
1177
1183
                }
1178
1184
        }
1179
1185
 
1180
 
        _unlock_mutex();
1181
 
        return _registered_device(message_data, hit);
 
1186
      reg:
 
1187
        ret = _registered_device(message_data, hit);
1182
1188
 
1183
1189
      out:
1184
1190
        _unlock_mutex();
1185
 
        
1186
 
        return -ENOENT;
 
1191
 
 
1192
        return ret;
1187
1193
}
1188
1194
 
1189
1195
static int _get_registered_device(struct message_data *message_data)
1241
1247
/* Open fifos used for client communication. */
1242
1248
static int _open_fifos(struct dm_event_fifos *fifos)
1243
1249
{
1244
 
        int orig_errno;
1245
1250
        struct stat st;
1246
1251
 
1247
1252
        /* Create client fifo. */
1248
1253
        (void) dm_prepare_selinux_context(fifos->client_path, S_IFIFO);
1249
1254
        if ((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) {
1250
 
                syslog(LOG_ERR, "%s: Failed to create client fifo.\n", __func__);
1251
 
                orig_errno = errno;
 
1255
                syslog(LOG_ERR, "%s: Failed to create client fifo %s: %m.\n",
 
1256
                       __func__, fifos->client_path);
1252
1257
                (void) dm_prepare_selinux_context(NULL, 0);
1253
 
                stack;
1254
 
                return -orig_errno;
 
1258
                return 0;
1255
1259
        }
1256
1260
 
1257
1261
        /* Create server fifo. */
1258
1262
        (void) dm_prepare_selinux_context(fifos->server_path, S_IFIFO);
1259
1263
        if ((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST) {
1260
 
                syslog(LOG_ERR, "%s: Failed to create server fifo.\n", __func__);
1261
 
                orig_errno = errno;
 
1264
                syslog(LOG_ERR, "%s: Failed to create server fifo %s: %m.\n",
 
1265
                       __func__, fifos->server_path);
1262
1266
                (void) dm_prepare_selinux_context(NULL, 0);
1263
 
                stack;
1264
 
                return -orig_errno;
 
1267
                return 0;
1265
1268
        }
1266
1269
 
1267
1270
        (void) dm_prepare_selinux_context(NULL, 0);
1268
1271
 
1269
1272
        /* Warn about wrong permissions if applicable */
1270
1273
        if ((!stat(fifos->client_path, &st)) && (st.st_mode & 0777) != 0600)
1271
 
                syslog(LOG_WARNING, "Fixing wrong permissions on %s",
 
1274
                syslog(LOG_WARNING, "Fixing wrong permissions on %s: %m.\n",
1272
1275
                       fifos->client_path);
1273
1276
 
1274
1277
        if ((!stat(fifos->server_path, &st)) && (st.st_mode & 0777) != 0600)
1275
 
                syslog(LOG_WARNING, "Fixing wrong permissions on %s",
 
1278
                syslog(LOG_WARNING, "Fixing wrong permissions on %s: %m.\n",
1276
1279
                       fifos->server_path);
1277
1280
 
1278
1281
        /* If they were already there, make sure permissions are ok. */
1279
1282
        if (chmod(fifos->client_path, 0600)) {
1280
 
                syslog(LOG_ERR, "Unable to set correct file permissions on %s",
 
1283
                syslog(LOG_ERR, "Unable to set correct file permissions on %s: %m.\n",
1281
1284
                       fifos->client_path);
1282
 
                return -errno;
 
1285
                return 0;
1283
1286
        }
1284
1287
 
1285
1288
        if (chmod(fifos->server_path, 0600)) {
1286
 
                syslog(LOG_ERR, "Unable to set correct file permissions on %s",
 
1289
                syslog(LOG_ERR, "Unable to set correct file permissions on %s: %m.\n",
1287
1290
                       fifos->server_path);
1288
 
                return -errno;
 
1291
                return 0;
1289
1292
        }
1290
1293
 
1291
1294
        /* Need to open read+write or we will block or fail */
1292
1295
        if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
1293
 
                stack;
1294
 
                return -errno;
 
1296
                syslog(LOG_ERR, "Failed to open fifo server %s: %m.\n",
 
1297
                       fifos->server_path);
 
1298
                return 0;
1295
1299
        }
1296
1300
 
1297
1301
        /* Need to open read+write for select() to work. */
1298
1302
        if ((fifos->client = open(fifos->client_path, O_RDWR)) < 0) {
1299
 
                stack;
1300
 
                close(fifos->server);
1301
 
                return -errno;
 
1303
                syslog(LOG_ERR, "Failed to open fifo client %s: %m", fifos->client_path);
 
1304
                if (close(fifos->server))
 
1305
                        syslog(LOG_ERR, "Failed to close fifo server %s: %m", fifos->server_path);
 
1306
                return 0;
1302
1307
        }
1303
1308
 
1304
 
        return 0;
 
1309
        return 1;
1305
1310
}
1306
1311
 
1307
1312
/*
1488
1493
        if (!_client_write(fifos, &msg))
1489
1494
                stack;
1490
1495
 
 
1496
        dm_free(msg.data);
 
1497
 
1491
1498
        if (die) raise(9);
1492
 
 
1493
 
        dm_free(msg.data);
1494
1499
}
1495
1500
 
1496
1501
static void _process_initial_registrations(void)
1501
1506
 
1502
1507
        while ((reg = _initial_registrations[i])) {
1503
1508
                msg.cmd = DM_EVENT_CMD_REGISTER_FOR_EVENT;
1504
 
                msg.size = strlen(reg);
1505
 
                msg.data = reg;
1506
 
                _do_process_request(&msg);
 
1509
                if ((msg.size = strlen(reg))) {
 
1510
                        msg.data = reg;
 
1511
                        _do_process_request(&msg);
 
1512
                }
1507
1513
                ++ i;
1508
1514
        }
1509
1515
}
1513
1519
        int ret;
1514
1520
        struct dm_list *l;
1515
1521
        struct thread_status *thread;
 
1522
        int join_ret = 0;
1516
1523
 
1517
1524
        _lock_mutex();
1518
1525
        while ((l = dm_list_first(&_thread_registry_unused))) {
1552
1559
 
1553
1560
                if (thread->status == DM_THREAD_DONE) {
1554
1561
                        dm_list_del(l);
1555
 
                        pthread_join(thread->thread, NULL);
 
1562
                        join_ret = pthread_join(thread->thread, NULL);
1556
1563
                        _free_thread_status(thread);
1557
1564
                }
1558
1565
        }
1559
1566
 
1560
1567
        _unlock_mutex();
 
1568
 
 
1569
        if (join_ret)
 
1570
                syslog(LOG_ERR, "Failed pthread_join: %s\n", strerror(join_ret));
1561
1571
}
1562
1572
 
1563
1573
static void _sig_alarm(int signum __attribute__((unused)))
1630
1640
/*
1631
1641
 * Protection against OOM killer if kernel supports it
1632
1642
 */
1633
 
static int _protect_against_oom_killer()
 
1643
static int _protect_against_oom_killer(void)
1634
1644
{
1635
1645
        struct stat st;
1636
1646
 
1653
1663
 
1654
1664
        return _set_oom_adj(OOM_ADJ_FILE, OOM_SCORE_ADJ_MIN);
1655
1665
}
 
1666
 
 
1667
static int _handle_preloaded_fifo(int fd, const char *path)
 
1668
{
 
1669
        struct stat st_fd, st_path;
 
1670
        int flags;
 
1671
 
 
1672
        if ((flags = fcntl(fd, F_GETFD)) < 0)
 
1673
                return 0;
 
1674
 
 
1675
        if (flags & FD_CLOEXEC)
 
1676
                return 0;
 
1677
 
 
1678
        if (fstat(fd, &st_fd) < 0 || !S_ISFIFO(st_fd.st_mode))
 
1679
                return 0;
 
1680
 
 
1681
        if (stat(path, &st_path) < 0 ||
 
1682
            st_path.st_dev != st_fd.st_dev ||
 
1683
            st_path.st_ino != st_fd.st_ino)
 
1684
                return 0;
 
1685
 
 
1686
        if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
 
1687
                return 0;
 
1688
 
 
1689
        return 1;
 
1690
}
 
1691
 
 
1692
static int _systemd_handover(struct dm_event_fifos *fifos)
 
1693
{
 
1694
        const char *e;
 
1695
        char *p;
 
1696
        unsigned long env_pid, env_listen_fds;
 
1697
        int r = 0;
 
1698
 
 
1699
        memset(fifos, 0, sizeof(*fifos));
 
1700
 
 
1701
        /* LISTEN_PID must be equal to our PID! */
 
1702
        if (!(e = getenv(SD_LISTEN_PID_ENV_VAR_NAME)))
 
1703
                goto out;
 
1704
 
 
1705
        errno = 0;
 
1706
        env_pid = strtoul(e, &p, 10);
 
1707
        if (errno || !p || *p || env_pid <= 0 ||
 
1708
            getpid() != (pid_t) env_pid)
 
1709
                goto out;
 
1710
 
 
1711
        /* LISTEN_FDS must be 2 and the fds must be FIFOSs! */
 
1712
        if (!(e = getenv(SD_LISTEN_FDS_ENV_VAR_NAME)))
 
1713
                goto out;
 
1714
 
 
1715
        errno = 0;
 
1716
        env_listen_fds = strtoul(e, &p, 10);
 
1717
        if (errno || !p || *p || env_listen_fds != 2)
 
1718
                goto out;
 
1719
 
 
1720
        /* Check and handle the FIFOs passed in */
 
1721
        r = (_handle_preloaded_fifo(SD_FD_FIFO_SERVER, DM_EVENT_FIFO_SERVER) &&
 
1722
             _handle_preloaded_fifo(SD_FD_FIFO_CLIENT, DM_EVENT_FIFO_CLIENT));
 
1723
 
 
1724
        if (r) {
 
1725
                fifos->server = SD_FD_FIFO_SERVER;
 
1726
                fifos->server_path = DM_EVENT_FIFO_SERVER;
 
1727
                fifos->client = SD_FD_FIFO_CLIENT;
 
1728
                fifos->client_path = DM_EVENT_FIFO_CLIENT;
 
1729
        }
 
1730
 
 
1731
out:
 
1732
        unsetenv(SD_LISTEN_PID_ENV_VAR_NAME);
 
1733
        unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
 
1734
        return r;
 
1735
}
1656
1736
#endif
1657
1737
 
1658
1738
static void remove_lockfile(void)
1719
1799
                fd = rlim.rlim_cur;
1720
1800
 
1721
1801
        for (--fd; fd >= 0; fd--) {
 
1802
#ifdef linux
1722
1803
                /* Do not close fds preloaded by systemd! */
1723
1804
                if (_systemd_activation &&
1724
1805
                    (fd == SD_FD_FIFO_SERVER || fd == SD_FD_FIFO_CLIENT))
1725
1806
                        continue;
1726
 
                close(fd);
 
1807
#endif
 
1808
                (void) close(fd);
1727
1809
        }
1728
1810
 
1729
1811
        if ((open("/dev/null", O_RDONLY) < 0) ||
1778
1860
                }
1779
1861
        }
1780
1862
 
1781
 
        _initial_registrations = dm_malloc(sizeof(char*) * (count + 1));
 
1863
        if (!(_initial_registrations = dm_malloc(sizeof(char*) * (count + 1)))) {
 
1864
                fprintf(stderr, "Memory allocation registration failed.\n");
 
1865
                exit(EXIT_FAILURE);
 
1866
        }
 
1867
 
1782
1868
        for (i = 0; i < count; ++i) {
1783
 
                _initial_registrations[i] = dm_strdup(message);
 
1869
                if (!(_initial_registrations[i] = dm_strdup(message))) {
 
1870
                        fprintf(stderr, "Memory allocation for message failed.\n");
 
1871
                        exit(EXIT_FAILURE);
 
1872
                }
1784
1873
                message += strlen(message) + 1;
1785
1874
        }
1786
1875
        _initial_registrations[count] = 0;
1793
1882
        fini_fifos(&fifos);
1794
1883
}
1795
1884
 
1796
 
static int _handle_preloaded_fifo(int fd, const char *path)
1797
 
{
1798
 
        struct stat st_fd, st_path;
1799
 
        int flags;
1800
 
 
1801
 
        if ((flags = fcntl(fd, F_GETFD)) < 0)
1802
 
                return 0;
1803
 
 
1804
 
        if (flags & FD_CLOEXEC)
1805
 
                return 0;
1806
 
 
1807
 
        if (fstat(fd, &st_fd) < 0 || !S_ISFIFO(st_fd.st_mode))
1808
 
                return 0;
1809
 
 
1810
 
        if (stat(path, &st_path) < 0 ||
1811
 
            st_path.st_dev != st_fd.st_dev ||
1812
 
            st_path.st_ino != st_fd.st_ino)
1813
 
                return 0;
1814
 
 
1815
 
        if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
1816
 
                return 0;
1817
 
 
1818
 
        return 1;
1819
 
}
1820
 
 
1821
 
static int _systemd_handover(struct dm_event_fifos *fifos)
1822
 
{
1823
 
        const char *e;
1824
 
        char *p;
1825
 
        unsigned long env_pid, env_listen_fds;
1826
 
        int r = 0;
1827
 
 
1828
 
        memset(fifos, 0, sizeof(*fifos));
1829
 
 
1830
 
        /* LISTEN_PID must be equal to our PID! */
1831
 
        if (!(e = getenv(SD_LISTEN_PID_ENV_VAR_NAME)))
1832
 
                goto out;
1833
 
 
1834
 
        errno = 0;
1835
 
        env_pid = strtoul(e, &p, 10);
1836
 
        if (errno || !p || *p || env_pid <= 0 ||
1837
 
            getpid() != (pid_t) env_pid)
1838
 
                goto out;
1839
 
 
1840
 
        /* LISTEN_FDS must be 2 and the fds must be FIFOSs! */
1841
 
        if (!(e = getenv(SD_LISTEN_FDS_ENV_VAR_NAME)))
1842
 
                goto out;
1843
 
 
1844
 
        errno = 0;
1845
 
        env_listen_fds = strtoul(e, &p, 10);
1846
 
        if (errno || !p || *p || env_listen_fds != 2)
1847
 
                goto out;
1848
 
 
1849
 
        /* Check and handle the FIFOs passed in */
1850
 
        r = (_handle_preloaded_fifo(SD_FD_FIFO_SERVER, DM_EVENT_FIFO_SERVER) &&
1851
 
             _handle_preloaded_fifo(SD_FD_FIFO_CLIENT, DM_EVENT_FIFO_CLIENT));
1852
 
 
1853
 
        if (r) {
1854
 
                fifos->server = SD_FD_FIFO_SERVER;
1855
 
                fifos->server_path = DM_EVENT_FIFO_SERVER;
1856
 
                fifos->client = SD_FD_FIFO_CLIENT;
1857
 
                fifos->client_path = DM_EVENT_FIFO_CLIENT;
1858
 
        }
1859
 
 
1860
 
out:
1861
 
        unsetenv(SD_LISTEN_PID_ENV_VAR_NAME);
1862
 
        unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
1863
 
        return r;
1864
 
}
1865
 
 
1866
1885
static void usage(char *prog, FILE *file)
1867
1886
{
1868
1887
        fprintf(file, "Usage:\n"
1869
 
                "%s [-V] [-h] [-d] [-d] [-d] [-f]\n\n"
1870
 
                "   -V       Show version of dmeventd\n"
1871
 
                "   -h       Show this help information\n"
 
1888
                "%s [-d [-d [-d]]] [-f] [-h] [-R] [-V] [-?]\n\n"
1872
1889
                "   -d       Log debug messages to syslog (-d, -dd, -ddd)\n"
1873
 
                "   -f       Don't fork, run in the foreground\n\n", prog);
 
1890
                "   -f       Don't fork, run in the foreground\n"
 
1891
                "   -h -?    Show this help information\n"
 
1892
                "   -R       Restart dmeventd\n"
 
1893
                "   -V       Show version of dmeventd\n\n", prog);
1874
1894
}
1875
1895
 
1876
1896
int main(int argc, char *argv[])
1902
1922
                case 'V':
1903
1923
                        printf("dmeventd version: %s\n", DM_LIB_VERSION);
1904
1924
                        exit(1);
1905
 
                        break;
1906
1925
                }
1907
1926
        }
1908
1927
 
1917
1936
        if (_restart)
1918
1937
                restart();
1919
1938
 
 
1939
#ifdef linux
1920
1940
        _systemd_activation = _systemd_handover(&fifos);
 
1941
#endif
1921
1942
 
1922
1943
        if (!_foreground)
1923
1944
                _daemonize();
1954
1975
 
1955
1976
        pthread_mutex_init(&_global_mutex, NULL);
1956
1977
 
1957
 
        if (!_systemd_activation && _open_fifos(&fifos))
 
1978
        if (!_systemd_activation && !_open_fifos(&fifos))
1958
1979
                exit(EXIT_FIFO_FAILURE);
1959
1980
 
1960
1981
        /* Signal parent, letting them know we are ready to go. */
1968
1989
        while (!_exit_now) {
1969
1990
                _process_request(&fifos);
1970
1991
                _cleanup_unused_threads();
 
1992
                _lock_mutex();
1971
1993
                if (!dm_list_empty(&_thread_registry)
1972
1994
                    || !dm_list_empty(&_thread_registry_unused))
1973
1995
                        _thread_registries_empty = 0;
1974
1996
                else
1975
1997
                        _thread_registries_empty = 1;
 
1998
                _unlock_mutex();
1976
1999
        }
1977
2000
 
1978
2001
        _exit_dm_lib();