dahdi_cfg: Wait for all spans to be assigned.
authorShaun Ruffell <sruffell@digium.com>
Mon, 9 Dec 2013 23:19:23 +0000 (17:19 -0600)
committerShaun Ruffell <sruffell@digium.com>
Thu, 12 Dec 2013 15:08:51 +0000 (09:08 -0600)
When auto span assignment is disabled, it's possible that simply running

  # /etc/init.d/dahdi restart

Will fail since dahdi_cfg can run in parallel with udev scripts that are
assigning spans, which results in /etc/dahdi/system.conf describing spans that
do not exist in the system.

This change sets up dahdi_cfg, when run without the -C or -S options, to look in
sysfs and make sure all spans for each device are assigned.  dahdi_cfg will wait
5 seconds for span assignment to happen before proceeding normally.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>

dahdi_cfg.c

index 349a0af..0de1091 100644 (file)
@@ -36,6 +36,8 @@
 #include <sys/ioctl.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <dirent.h>
+#include <stdbool.h>
 
 #include <dahdi/user.h>
 #include "tonezone.h"
@@ -137,6 +139,84 @@ static const char *laws[] = {
        "A-law"
 };
 
+static bool _are_all_spans_assigned(const char *device_path)
+{
+       char attribute[1024];
+       int res;
+       FILE *fp;
+       int span_count;
+       DIR *dirp;
+       struct dirent *dirent;
+
+       snprintf(attribute, sizeof(attribute) - 1,
+                "%s/span_count", device_path);
+       fp = fopen(attribute, "r");
+       if (NULL == fp) {
+               fprintf(stderr, "Failed to open '%s'.\n", attribute);
+               return false;
+       }
+       res = fscanf(fp, "%d", &span_count);
+       fclose(fp);
+
+       if (EOF == res) {
+               fprintf(stderr, "Failed to read '%s'.\n", attribute);
+               return false;
+       }
+
+       dirp = opendir(device_path);
+       while (span_count) {
+               dirent = readdir(dirp);
+               if (NULL == dirent)
+                       break;
+               if (!strncmp("span-", dirent->d_name, 5)) {
+                       --span_count;
+               }
+       }
+       closedir(dirp);
+       return (span_count > 0) ? false : true;
+}
+
+/**
+ * are_all_spans_assigned - Look in sysfs to see if all spans for a device are assigned.
+ *
+ * Returns true if there are $span_count child spans of all devices, or false
+ *  otherwise.
+ */
+static bool are_all_spans_assigned(void)
+{
+       DIR *dirp;
+       struct dirent *dirent;
+       bool res = true;
+       char device_path[1024];
+
+       dirp = opendir("/sys/bus/dahdi_devices/devices");
+       if (!dirp) {
+               /* If we cannot open dahdi_devices, either dahdi isn't loaded,
+                * or we're using an older version of DAHDI that doesn't use
+                * sysfs. */
+               return true;
+       }
+
+       while (true && res) {
+
+               dirent = readdir(dirp);
+               if (NULL == dirent)
+                       break;
+
+               if (!strcmp(dirent->d_name, ".") ||
+                   !strcmp(dirent->d_name, ".."))
+                       continue;
+
+               snprintf(device_path, sizeof(device_path)-1,
+                        "/sys/bus/dahdi_devices/devices/%s", dirent->d_name);
+               res = _are_all_spans_assigned(device_path);
+       }
+
+       closedir(dirp);
+       errno = 0;
+       return res;
+}
+
 static const char *sigtype_to_str(const int sig)
 {
        switch (sig) {
@@ -1495,6 +1575,21 @@ int main(int argc, char *argv[])
                fprintf(stderr, "%s\n", dahdi_tools_version);
        }
 
+       if (!restrict_channels && !only_span) {
+               bool all_assigned = are_all_spans_assigned();
+               unsigned int timeout = 4*5; /* We'll wait 5 seconds */
+
+               while (!all_assigned && --timeout) {
+                       usleep(250000);
+                       all_assigned = are_all_spans_assigned();
+               }
+
+               if (0 == timeout) {
+                       fprintf(stderr,
+                               "Timeout waiting for all spans to be assigned.\n");
+               }
+       }
+
        if (fd == -1) fd = open(MASTER_DEVICE, O_RDWR);
        if (fd < 0) {
                error("Unable to open master device '%s'\n", MASTER_DEVICE);