Add -l option to ibsrpdm.
This option activates a daemon that queries for the targets in a loop and
tells ib_srp about new target that appears and old target that disappears.

Signed-off-by: Ishai Rabinovitz <[EMAIL PROTECTED]>

Index: last_stable/src/userspace/srptools/src/srp-dm.c
===================================================================
--- last_stable.orig/src/userspace/srptools/src/srp-dm.c        2006-04-21 
04:47:54.000000000 +0300
+++ last_stable/src/userspace/srptools/src/srp-dm.c     2006-04-21 
05:16:11.000000000 +0300
@@ -35,6 +35,7 @@
 #include <byteswap.h>
 #include <errno.h>
 #include <getopt.h>
+#include <syslog.h>
 
 #include "ib_user_mad.h"
 #include "srp-dm.h"
@@ -49,17 +50,39 @@ static uint32_t tid = 1;
 
 static int cmd     = 0;
 static int verbose = 0;
+static int loop    = 0;
+static int add_target_fd;
+static int remove_target_fd;
+static char *list_targets_path;
+
+#define pr_log(arg...)                                         \
+       do {                                                    \
+               if (verbose) {                                  \
+                       if (loop)                               \
+                               syslog(LOG_WARNING, arg);       \
+                       else if (!cmd)                          \
+                               printf(arg);                    \
+               }                                               \
+       } while (0)
 
 #define pr_human(arg...)                       \
        do {                                    \
-               if (!cmd)                       \
+               if (!cmd && !loop)              \
                        printf(arg);            \
        } while (0)
 
 #define pr_cmd(arg...)                         \
        do {                                    \
-               if (cmd)                        \
-                       printf(arg);            \
+               if (cmd && !loop)               \
+                       printf(arg);            \
+       } while (0)
+
+#define pr_err(arg...)                                 \
+       do {                                            \
+               if (loop)                               \
+                       syslog(LOG_WARNING, arg);       \
+               else                                    \
+                       fprintf(stderr, arg);           \
        } while (0)
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -78,11 +101,106 @@ static inline uint64_t htonll(uint64_t x
 
 #define N_COMP_MASK_LID htonll(1);
 
+#define INITIAL_SIZE_OF_TARGET_TABLE 10
+
+#define SLEEP_TIME 60
+
+static int size_of_target_table = INITIAL_SIZE_OF_TARGET_TABLE;
+
+/* Implementaion of target set in an array.
+*  Assumption: there will be small number of targets
+*  TODO: If this assumption does not hold,
+*        change the implemantaion to a hash or a tree
+*/
+
+typedef struct {
+       char **array;
+       unsigned int next_index;
+       unsigned int size;
+} targets_set;
+
+static int create_set(targets_set *set)
+{
+       set->next_index = 0;
+       set->size = size_of_target_table;
+       set->array = calloc(set->size, sizeof(char *));
+       if (set->array == NULL) {
+               perror("calloc:");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int add_to_set(targets_set *set, char *target_info)
+{
+       if (set->next_index == set->size) {
+               if (set->size == size_of_target_table)
+                       size_of_target_table *= 2;
+               set->size = size_of_target_table;
+               set->array = realloc(set->array, set->size * sizeof(char *));
+               if (set->array == NULL) {
+                       pr_err("realloc: %s\n", strerror(errno));
+                       return -1;
+               }
+       }
+       set->array[set->next_index] = strdup(target_info);
+       if (set->array[set->next_index] == NULL) {
+               pr_err("strdup: %s\n", strerror(errno));
+               return -1;
+       }
+       ++set->next_index;
+
+       return 0;
+}
+
+static int remove_from_set(targets_set *set, char *target_info)
+{
+       int i;
+
+       for (i = 0; i < set->next_index; ++i)
+               if (!strcmp(set->array[i], target_info)) {
+                       free(set->array[i]);
+                       set->array[i] = set->array[set->next_index];
+                       --set->next_index;
+                       return 0;
+               }
+
+       return -1;
+}
+
+static void empty_set(targets_set *set)
+{
+       int i;
+
+       for (i = 0; i < set->next_index; ++i)
+               free(set->array[i]);
+       set->next_index = 0;
+}
+
+static void destroy_set(targets_set *set)
+{
+       int i;
+
+       empty_set(set);
+       free(set->array);
+}
+
+/* for_each_entry_in_set(char *target, targets_set *set, int i) */
+#define for_each_entry_in_set(target, set, i)  \
+       for (i = 0, target = set->array[i];     \
+            i < set->next_index;               \
+            ++i, target = set->array[i])
+
+/* End of the impemantaion of the set */
+
+targets_set *targets_in_kernel_set;
+
 static char *sysfs_path = "/sys";
 
 static void usage(const char *argv0)
 {
-       fprintf(stderr, "Usage: %s [-vc] [-d <umad device>]\n", argv0);
+       fprintf(stderr, "Usage: %s [-vcl] [-d <umad device>]\n", argv0);
 }
 
 #define NUM_OF_RETRIES 3
@@ -97,7 +215,7 @@ int send_and_get(int fd, struct ib_user_
        {
                len = write(fd, out_mad, sizeof(struct ib_user_mad));
               if (len != sizeof(struct ib_user_mad)) {
-                       fprintf(stderr, "write: %s\n", strerror(errno));
+                       pr_err("write: %s\n", strerror(errno));
                        return -1;
                }
 
@@ -106,7 +224,7 @@ int send_and_get(int fd, struct ib_user_
                    (in_mad_size != 0 && len > 0))
                        return len;
                else if (in_mad->hdr.status != ETIMEDOUT) {
-                       fprintf(stderr, "%s/%d: read: %s\n", __func__, 
__LINE__, strerror(errno));
+                       pr_err("%s/%d: read: %s\n", __func__, __LINE__, 
strerror(errno));
                        return -1;
                }
                out_dm_mad = (void *) out_mad->data;
@@ -181,6 +299,37 @@ static int setup_port_sysfs_path(void) {
        asprintf(&port_sysfs_path, "%s/class/infiniband/%s/ports/%s",
                 sysfs_path, ibdev, ibport);
 
+       if (loop) {
+               char *add_target_path, *remove_target_path;
+
+               asprintf(&add_target_path,
+                                "%s/class/infiniband_srp/srp-%s-%s/add_target",
+                        sysfs_path, ibdev, ibport);
+
+               add_target_fd = open(add_target_path, O_WRONLY);
+               if (add_target_fd < 0) {
+                       pr_err("Couldn't open %s\n", add_target_path);
+                       return -1;
+               }
+
+               free(add_target_path);
+               asprintf(&remove_target_path,
+                                
"%s/class/infiniband_srp/srp-%s-%s/remove_target",
+                                sysfs_path, ibdev, ibport);
+
+               remove_target_fd = open(remove_target_path, O_WRONLY);
+               if (remove_target_fd < 0) {
+                       pr_err("Couldn't open %s\n", remove_target_path);
+                       return -1;
+               }
+
+               free(remove_target_path);
+       }
+
+       asprintf(&list_targets_path,
+                "%s/class/infiniband_srp/srp-%s-%s/list_targets",
+                sysfs_path, ibdev, ibport);
+
        return 0;
 }
 
@@ -248,14 +397,14 @@ static int set_class_port_info(int fd, u
        cpi                = (void *) out_dm_mad->data;
 
        if (read_file(port_sysfs_path, "lid", val, sizeof val) < 0) {
-               fprintf(stderr, "Couldn't read LID\n");
+               pr_err("Couldn't read LID\n");
                return -1;
        }
 
        cpi->trap_lid = htons(strtol(val, NULL, 0));
 
        if (read_file(port_sysfs_path, "gids/0", val, sizeof val) < 0) {
-               fprintf(stderr, "Couldn't read GID[0]\n");
+               pr_err("Couldn't read GID[0]\n");
                return -1;
        }
 
@@ -268,7 +417,7 @@ static int set_class_port_info(int fd, u
 
        in_dm_mad = (void *) in_mad.data;
        if (in_dm_mad->status) {
-               fprintf(stderr, "Class Port Info query returned status 
0x%04x\n",
+               pr_err("Class Port Info query returned status 0x%04x\n",
                        ntohs(in_dm_mad->status));
                return -1;
        }
@@ -289,7 +438,7 @@ static int get_iou_info(int fd, uint32_t
 
        in_dm_mad = (void *) in_mad.data;
        if (in_dm_mad->status) {
-               fprintf(stderr, "IO Unit Info query returned status 0x%04x\n",
+               pr_err("IO Unit Info query returned status 0x%04x\n",
                        ntohs(in_dm_mad->status));
                return -1;
        }
@@ -311,13 +460,13 @@ static int get_ioc_prof(int fd, uint32_t
                return -1;
 
        if (in_mad.hdr.status != 0) {
-               fprintf(stderr, "IO Controller Profile query timed out\n");
+               pr_err("IO Controller Profile query timed out\n");
                return -1;
        }
 
        in_dm_mad = (void *) in_mad.data;
        if (in_dm_mad->status) {
-               fprintf(stderr, "IO Controller Profile query returned status 
0x%04x\n",
+               pr_err("IO Controller Profile query returned status 0x%04x\n",
                        ntohs(in_dm_mad->status));
                return -1;
        }
@@ -340,13 +489,13 @@ static int get_svc_entries(int fd, uint3
                return -1;
 
        if (in_mad.hdr.status != 0) {
-               fprintf(stderr, "Service Entries query timed out\n");
+               pr_err("Service Entries query timed out\n");
                return -1;
        }
 
        in_dm_mad = (void *) in_mad.data;
        if (in_dm_mad->status) {
-               fprintf(stderr, "Service Entries query returned status 
0x%04x\n",
+               pr_err("Service Entries query returned status 0x%04x\n",
                        ntohs(in_dm_mad->status));
                return -1;
        }
@@ -356,17 +505,57 @@ static int get_svc_entries(int fd, uint3
        return 0;
 }
 
+int add_target(char *new_target, int len)
+{
+       int ret;
+
+       ret = remove_from_set(targets_in_kernel_set, new_target);
+       if (ret == 0)
+               return 0;
+
+       /* It is a new target */
+       if (verbose)
+               pr_log("Writing new target %s\n", new_target);
+       if (write(add_target_fd, new_target, len) != len) {
+               pr_err("write: %s\n", strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}
+
+void free_old_targets()
+{
+       char *target;
+       int i;
+
+       for_each_entry_in_set(target, targets_in_kernel_set, i) {
+               int len = strlen(target);
+               if (verbose)
+                      pr_log("Removing target %s\n", target);
+               if (write(remove_target_fd, target, len) != len)
+                       if (errno != EEXIST) {
+                               /* could not remove the target
+                                  and not because it is not exist*/
+                               pr_err("write: %s\n", strerror(errno));
+                               continue;
+                       }
+       }
+       empty_set(targets_in_kernel_set);
+}
+
 static int do_port(int fd, uint32_t agent[2], uint16_t dlid, uint64_t 
subnet_prefix,
                   uint64_t guid)
 {
        struct srp_dm_iou_info          iou_info;
        struct srp_dm_ioc_prof          ioc_prof;
        struct srp_dm_svc_entries       svc_entries;
-       int                             i, j, k;
+       int                             i, j, k, len;
+       char                           *target_info;
 
        if (!memcmp(&guid, topspin_oui, 3) &&
            set_class_port_info(fd, agent, dlid))
-               fprintf(stderr, "Warning: set of ClassPortInfo failed\n");
+               pr_log("Warning: set of ClassPortInfo failed\n");
 
        if (get_iou_info(fd, agent, dlid, &iou_info))
                return 1;
@@ -431,22 +620,31 @@ static int do_port(int fd, uint32_t agen
                                                 (unsigned long long) 
ntohll(svc_entries.service[k].id),
                                                 svc_entries.service[k].name);
 
-                                       pr_cmd("id_ext=%s,"
+                                       len = asprintf(&target_info, 
"id_ext=%s,"
                                               "ioc_guid=%016llx,"
                                               "dgid=%016llx%016llx,"
                                               "pkey=ffff,"
-                                              "service_id=%016llx\n",
+                                              "service_id=%016llx",
                                               id_ext,
                                               (unsigned long long) 
ntohll(ioc_prof.guid),
                                               (unsigned long long) 
subnet_prefix,
                                               (unsigned long long) guid,
                                               (unsigned long long) 
ntohll(svc_entries.service[k].id));
+                                       if (len < 0) {
+                                               pr_err("Cannot create 
target_info\n");
+                                               return -1;
+                                       }
+
+                                       pr_cmd("%s\n", target_info);
+
+                                       if (loop)
+                                               add_target(target_info, len);
                                }
                        }
                }
        }
 
-       pr_human("\n");
+       pr_log("\n");
 
        return 0;
 }
@@ -495,7 +693,7 @@ static int get_port_list(int fd, uint32_
        int isdm;
 
        if (read_file(port_sysfs_path, "sm_lid", val, sizeof val) < 0) {
-               fprintf(stderr, "Couldn't read SM LID\n");
+               pr_err("Couldn't read SM LID\n");
                return -1;
        }
 
@@ -537,16 +735,45 @@ static int get_port_list(int fd, uint32_
        return 0;
 }
 
+#define TARGET_INFO_SIZE 126
+static int get_existing_targets()
+{
+       char buf[TARGET_INFO_SIZE];
+       int list_targets_fd;
+       int ret;
+
+       list_targets_fd = open(list_targets_path, O_RDONLY);
+       if (list_targets_fd < 0) {
+               pr_err("Couldn't open %s\n", list_targets_path);
+               return -1;
+       }
+
+       ret = read(list_targets_fd, buf, TARGET_INFO_SIZE);
+       while (ret > 0) {
+               buf[ret - 1] = 0;
+               ret = add_to_set(targets_in_kernel_set, buf);
+               if (ret)
+                       return ret;
+               pr_log("found %s in the kernel\n", buf);
+               ret = read(list_targets_fd, buf, TARGET_INFO_SIZE);
+       }
+
+       close(list_targets_fd);
+       return 0;
+}
+
 int main(int argc, char *argv[])
 {
        int             fd;
        uint32_t        agent[0];
        char           *cmd_name = strdup(argv[0]);
+       pid_t           pid, sid;
+       int             ret;
 
        while (1) {
                int c;
 
-               c = getopt(argc, argv, "cvd:");
+               c = getopt(argc, argv, "cvld:");
                if (c == -1)
                        break;
 
@@ -560,25 +787,88 @@ int main(int argc, char *argv[])
                case 'v':
                        ++verbose;
                        break;
+               case 'l':
+                       ++loop;
+                       break;
                default:
                        usage(cmd_name);
                        return 1;
                }
        }
 
-       fd = open(umad_dev, O_RDWR);
+       fd = open(umad_dev, O_RDWR);
        if (fd < 0) {
                perror("open");
-               return 1;
+               exit(EXIT_FAILURE);
        }
 
        if (setup_port_sysfs_path())
-               return 1;
+               exit(EXIT_FAILURE);
 
        if (create_agent(fd, agent))
-               return 1;
+               exit(EXIT_FAILURE);
+
+       /* Daemon-specific initialization goes here */
+       targets_in_kernel_set = (targets_set *) malloc(sizeof(targets_set));
+       create_set(targets_in_kernel_set);
+
+       if (loop) {
+               /* Fork off the parent process */
+               pid = fork();
+               if (pid < 0) {
+                       exit(EXIT_FAILURE);
+               }
+               /* If we got a good PID, then
+                  we can exit the parent process. */
+               if (pid > 0) {
+                       exit(EXIT_SUCCESS);
+               }
+
+               /* Change the file mode mask */
+               umask(0);
+
+               /* Open any logs here */
+               openlog("ibsrpdm: ", LOG_NDELAY, LOG_DAEMON | LOG_SYSLOG);
+
+               /* Create a new SID for the child process */
+               sid = setsid();
+               if (sid < 0) {
+                       /* Log the failure */
+                       exit(EXIT_FAILURE);
+               }
+
+               /* Change the current working directory */
+               if ((chdir("/")) < 0) {
+                       /* Log the failure */
+                       exit(EXIT_FAILURE);
+               }
+
+               /* Close out the standard file descriptors */
+               close(STDIN_FILENO);
+               close(STDOUT_FILENO);
+               close(STDERR_FILENO);
+       }
+
+       /* The Big Loop */
+       while (1) {
+               if (loop)
+                       (void) get_existing_targets();
+
+               ret = get_port_list(fd, agent);
+               if (loop == 0)
+                       return ret;
+
+               free_old_targets();
+
+               sleep(SLEEP_TIME); /* wait SLEEP_TIME seconds */
+       }
 
-       get_port_list(fd, agent);
+       destroy_set(targets_in_kernel_set);
+       free(port_sysfs_path);
+       free(list_targets_path);
+       close(add_target_fd);
+       close(remove_target_fd);
+       closelog();
 
        return 0;
 }
-- 
Ishai Rabinovitz
_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to