[PATCH] Add cleanup routines.

2014-04-11 Thread Hannes Weisbach
Dynamically loaded library handles are saved in a list and dlclosed() on
exit. The list of struct ibv_driver *, as well as the global
struct ibv_device ** list are free()d.

Signed-off-by: Hannes Weisbach hannes_weisb...@gmx.net
---
 src/device.c | 10 ++
 src/init.c   | 51 ++-
 2 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/src/device.c b/src/device.c
index beb7b3c..d5b76bb 100644
--- a/src/device.c
+++ b/src/device.c
@@ -305,3 +305,13 @@ void __ibv_ack_async_event(struct ibv_async_event *event)
}
 }
 default_symver(__ibv_ack_async_event, ibv_ack_async_event);
+
+FINI static void ibverbs_deinit()
+{
+   size_t i;
+   for (i = 0; i  num_devices; i++) {
+   /* driver callback needed. May not be malloc'd memory */
+   free(device_list[i]);
+   }
+   free(device_list);
+}
diff --git a/src/init.c b/src/init.c
index d0e4b1c..2a8bca4 100644
--- a/src/init.c
+++ b/src/init.c
@@ -67,6 +67,11 @@ struct ibv_driver_name {
struct ibv_driver_name *next;
 };
 
+struct ibv_so_list {
+   void *dlhandle;
+   struct ibv_so_list *next;
+};
+
 struct ibv_driver {
const char *name;
ibv_driver_init_funcinit_func;
@@ -77,6 +82,7 @@ struct ibv_driver {
 static struct ibv_sysfs_dev *sysfs_dev_list;
 static struct ibv_driver_name *driver_name_list;
 static struct ibv_driver *head_driver, *tail_driver;
+static struct ibv_so_list *so_list;
 
 static int find_sysfs_devs(void)
 {
@@ -193,7 +199,14 @@ void verbs_register_driver(const char *name, 
verbs_driver_init_func init_func)
 static void load_driver(const char *name)
 {
char *so_name;
-   void *dlhandle;
+   struct ibv_so_list *elem;
+   struct ibv_so_list **list;
+
+   elem = malloc(sizeof(*elem));
+   if(!elem)
+   return;
+
+   elem-next = NULL;
 
 #define __IBV_QUOTE(x) #x
 #define IBV_QUOTE(x)   __IBV_QUOTE(x)
@@ -205,16 +218,25 @@ static void load_driver(const char *name)
 name)  0) {
fprintf(stderr, PFX Warning: couldn't load driver '%s'.\n,
name);
-   return;
+   goto err;
}
 
-   dlhandle = dlopen(so_name, RTLD_NOW);
-   if (!dlhandle) {
+   elem-dlhandle = dlopen(so_name, RTLD_NOW);
+   if (!elem-dlhandle) {
fprintf(stderr, PFX Warning: couldn't load driver '%s': %s\n,
name, dlerror());
-   goto out;
+   goto err;
}
 
+   for (list = so_list; *list; list = (*list)-next)
+   ;
+
+   *list = elem;
+
+   goto out;
+
+err:
+   free(elem);
 out:
free(so_name);
 }
@@ -573,3 +595,22 @@ out:
 
return num_devices;
 }
+
+FINI static void unload_drivers()
+{
+   struct ibv_driver *driver;
+   struct ibv_so_list * list;
+
+   for (driver = head_driver; driver;) {
+   struct ibv_driver *tmp = driver;
+   driver = driver-next;
+   free(tmp);
+   }
+
+   for (list = so_list; list;) {
+   struct ibv_so_list *tmp = list;
+   list = list-next;
+   dlclose(tmp-dlhandle);
+   free(tmp);
+   }
+}
-- 
1.8.5.5


--
To unsubscribe from this list: send the line unsubscribe linux-rdma in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] Clean index map on exit

2014-04-11 Thread Hannes Weisbach
This patch adds the function idm_free() to free all entries of an index
map. A call to this function is added in the ucma_cleanup destructor.
The ucma_idm struct index_map is cleaned.

Signed-off-by: Hannes Weisbach hannes_weisb...@gmx.net
---
 src/cma.c | 1 +
 src/indexer.c | 8 
 src/indexer.h | 1 +
 3 files changed, 10 insertions(+)

diff --git a/src/cma.c b/src/cma.c
index 0cf4203..a533bf9 100644
--- a/src/cma.c
+++ b/src/cma.c
@@ -139,6 +139,7 @@ static void ucma_cleanup(void)
ibv_close_device(cma_dev_array[cma_dev_cnt].verbs);
}
 
+   idm_free(ucma_idm);
fastlock_destroy(idm_lock);
free(cma_dev_array);
cma_dev_cnt = 0;
diff --git a/src/indexer.c b/src/indexer.c
index c8e8bce..4d1fd77 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -164,3 +164,11 @@ void *idm_clear(struct index_map *idm, int index)
entry[idx_entry_index(index)] = NULL;
return item;
 }
+
+void idm_free(struct index_map *idm)
+{
+   size_t i;
+   for (i = 0; i  IDX_ARRAY_SIZE; i++) {
+   free(idm-array[i]);
+   }
+}
diff --git a/src/indexer.h b/src/indexer.h
index 0c5f388..829d46b 100644
--- a/src/indexer.h
+++ b/src/indexer.h
@@ -89,6 +89,7 @@ struct index_map
 
 int idm_set(struct index_map *idm, int index, void *item);
 void *idm_clear(struct index_map *idm, int index);
+void idm_free(struct index_map *idm);
 
 static inline void *idm_at(struct index_map *idm, int index)
 {
-- 
1.8.5.5


--
To unsubscribe from this list: send the line unsubscribe linux-rdma in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Add cleanup routines.

2014-04-11 Thread Hannes Weisbach

Am 11.04.2014 um 19:00 schrieb Yann Droneaud ydrone...@opteya.com:

 Hi,
Thanks for your quick reply.

 Please adds some explanation, in particular the purpose of the changes.
 Your commit message only explain how, but you should also explain
 why.
Ok.

 In C, empty prototype declare a function which accept any parameter. So
 perhaps void ibverbs(void) is what you mean.
Yup, thanks.

 +{
 +size_t i;
 +for (i = 0; i  num_devices; i++) {
 +/* driver callback needed. May not be malloc'd memory */
 
 Seems dangerous. Such interrogation must be explicitly added in the
 commit message. 
Maybe it's better to leave it as a TODO and only free the device_list
itself?

 +for (driver = head_driver; driver;) {
 +struct ibv_driver *tmp = driver;
 +driver = driver-next;
 +free(tmp);
 +}
 +
 
 Is it safe here to free the driver ?
The struct itself is no longer needed.  All the driver libraries are
loaded and ibverbs_init() is call-once, so no new libraries are
dlopen()ed (and call ibv_register_driver()).
It's probably nicer first to dlclose() all libraries and then free all
struct ibv_drivers.

 +for (list = so_list; list;) {
 +struct ibv_so_list *tmp = list;
 +list = list-next;
 +dlclose(tmp-dlhandle);
 +free(tmp);
 +}
 +}
 
 Why not store the dlopen() handle in the struct ibv_driver itself ?
 This way only one list has to be scanned.
That was my first idea, but the struct ibv_driver doesn't exist at
that time.  First the (driver) library is dlopen()d and calls
ibv_register_driver().  Only there is the ibv_driver struct allocated,
but the handle is gone.

Best regards,
Hannes
--
To unsubscribe from this list: send the line unsubscribe linux-rdma in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Clean index map on exit

2014-04-11 Thread Hannes Weisbach

 
 Is the array always full ?
No, but it has to be zero-initialized and free(NULL) is fine.

idm_set() does:
if (!idm-array[idx_array_index(index)]) {
if (idm_grow(idm, index)  0)
(idm_grow does calloc().)

So I concluded unused entries have to be zero already and I don't put
a new constraint on struct index_map.

 is the maximum index of the array
 IDX_ARRAY_SIZE or could it be lower ?
It's fixed:
struct index_map
{
void **array[IDX_ARRAY_SIZE];
};

 And what about idm, is it free()'d somewhere else ?
The owner has to take care of its struct index_map.  I can only free
the resources the map itself holds.
For what it's worth: all struct index_maps are declared statically.

Again, thank you for your quick feedback.

Best regards,
Hannes
--
To unsubscribe from this list: send the line unsubscribe linux-rdma in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: RDMA read does not update local memory

2014-02-13 Thread Hannes Weisbach
Hello,

I found out that some code does madvise(MADV_DONTNEED) on the
allocated memory.  I think that this unmaps the memory from the user
space process.  If the process touches the memory again, a COW mapping
or even a new, zeroed out page is mapped in the process.  Either way,
the relation between the physical page, where the data from the RDMA
read ends up and the virtual page is broken.

I realize that calling madvise(MADV_DONTNEED) doesn’t have any meaning
for RDMA-registered memory.  I feel however that my observed behavior
is a bug and one of the following should happen:
. madvise() on pinned memory/I/O memory should fail, i.e. return EINVAL,
 EIO or ENOMEM (I didn’t test what happens when you call 
madvise(MADV_DONTNEED) on I/O mem.)
. RDMA actions on madvise()’d memory should fail.

Best regards,
Hannes Weisbach--
To unsubscribe from this list: send the line unsubscribe linux-rdma in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: RDMA read does not update local memory

2014-01-31 Thread Hannes Weisbach

Am 30.01.2014 um 22:36 schrieb Anuj Kalia anujkaliai...@gmail.com:

 Hannes,
 
 Have you tried marking the memory that is being read as volatile“?
Thanks for the suggestion, but I don’t think that this solves the
problem, because when I do:

memset(…);
rdma_post_read(…);
/* wait */
memcmp(…);

The compiler may not optimize across rdma_post_read() (or rather
ibv_post_send() and finally ioctl()), because these function may have
side-effects (which they do).
Anyway, I implemented a little helper memcmpv(volatile unsigned char *
s1, volatile unsiged char * s2, size_t size) to compare the memory as
volatile, but the memory still has the preset 0x55 instead of the
contents of the remote memory.
May that memset() be still in the cache, so that the memory accesses
of the CPU hit the cache instead of main memory?  I can’t imagine the
cache isn’t invalidated on reception of remote data.

Best regards,
Hannes--
To unsubscribe from this list: send the line unsubscribe linux-rdma in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: RDMA read does not update local memory

2014-01-31 Thread Hannes Weisbach

Am 31.01.2014 um 15:26 schrieb Anuj Kalia anujkaliai...@gmail.com:

 Are you sure that the compiler knows that post_send() has side effects?
No, thats why I tested with the mentioned memcmpv.  I examined the
emitted code with objdump and the compiler issued the mov instructions
to read the bytes from memory - still didn’t work.
I’ll leave the memcpyv in for the moment just to be sure.

Best regards,
Hannes--
To unsubscribe from this list: send the line unsubscribe linux-rdma in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RDMA read does not update local memory

2014-01-30 Thread Hannes Weisbach
Hello all,

I’m developing an (userspace) RDMA-application under Linux and came
across a problem, I’m not able to solve.

On machine A I had a chunk of memory registered with rdma_reg_read(),
so others can read from that memory later.
 Machine B has memory which is also registered with rdma_reg_read().
Machine B tells machine A about that memory and the rkey.
 Machine A rdma_post_read()s then from that memory on machine B in
it’s own memory.  The problem now is, that - although no error is
reported - the contents of machine A’s memory does not change.  I
memset() it to 0x55 before the rdma_post_read() for debugging
purposes and instead of having the contents I expect (an ASCII
string), the memory is still 0x55 after the work completion is
signaled.

Thus, I’ve allocated different chunks of memory using malloc() and
posix_memalign() with different sizes and registered them with
rdma_reg_read(), to see if that makes a difference.  The
rdma_post_read() works on all tested memory, except one chunk.

I don’t know what is different about that memory, where my mistake
might be or how to debug this.

Please note, that I check all return values for errors (there are
none) and also the work completion reports IBV_SUCCESS.
I hope you can give me some hints on how to proceed.
I apologize if my problem description was too brief; please ask for
details if I left important information out.

Best regards,
Hannes Weisbach--
To unsubscribe from this list: send the line unsubscribe linux-rdma in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


non-const pointer void * addr in rdma_reg_* and rdma_post_[send|write]

2013-11-27 Thread Hannes Weisbach
Hi,

I just started working with librdmacm and I was wondering if there is a 
specific reason why rdma_reg_* functions and rdma_post_send/write functions 
take the local memory address as non-const pointer void * addr. These 
functions shouldn't and don't change the memory pointed to by addr. I think 
this should be made explicit by using the type const void * for addr.
In case you agree, I would volunteer to make the necessary changes.

Best regards,
Hannes Weisbach--
To unsubscribe from this list: send the line unsubscribe linux-rdma in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html