[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