[openib-general] [PATCH 11/12] SRP: Changing ibsrpdm
Ishai Rabinovitz
ishai at mellanox.co.il
Mon May 1 04:31:16 PDT 2006
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 <ishai at mellanox.co.il>
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
More information about the general
mailing list