[ofa-general] Memory registration redux
Roland Dreier
rdreier at cisco.com
Tue May 26 16:13:58 PDT 2009
Here's the test program:
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#define UMMUNOT_INTF_VERSION 1
enum {
UMMUNOT_EVENT_TYPE_INVAL = 0,
UMMUNOT_EVENT_TYPE_LAST = 1,
};
enum {
UMMUNOT_EVENT_FLAG_HINT = 1 << 0,
};
/*
* If type field is INVAL, then user_cookie_counter holds the
* user_cookie for the region being reported; if the HINT flag is set
* then hint_start/hint_end hold the start and end of the mapping that
* was invalidated. (If HINT is not set, then multiple events
* invalidated parts of the registered range and hint_start/hint_end
* should be ignored)
*
* If type is LAST, then the read operation has emptied the list of
* invalidated regions, and user_cookie_counter holds the value of the
* kernel's generation counter when the empty list occurred. The
* other fields are not filled in for this event.
*/
struct ummunot_event {
__u32 type;
__u32 flags;
__u64 hint_start;
__u64 hint_end;
__u64 user_cookie_counter;
};
struct ummunot_register_ioctl {
__u32 intf_version; /* in */
__u32 reserved1;
__u64 start; /* in */
__u64 end; /* in */
__u64 user_cookie; /* in */
};
#define UMMUNOT_MAGIC 'U'
#define UMMUNOT_REGISTER_REGION _IOWR(UMMUNOT_MAGIC, 1, \
struct ummunot_register_ioctl)
#define UMMUNOT_UNREGISTER_REGION _IOW(UMMUNOT_MAGIC, 2, __u64)
static int umn_fd;
static volatile unsigned long long *umn_counter;
static int umn_init(void)
{
umn_fd = open("/dev/ummunot", O_RDONLY);
if (umn_fd < 0) {
perror("open");
return 1;
}
umn_counter = mmap(NULL, sizeof *umn_counter, PROT_READ,
MAP_SHARED, umn_fd, 0);
if (umn_counter == MAP_FAILED) {
perror("mmap");
return 1;
}
return 0;
}
static int umn_register(void *buf, size_t size, __u64 cookie)
{
struct ummunot_register_ioctl r = {
.intf_version = UMMUNOT_INTF_VERSION,
.start = (unsigned long) buf,
.end = (unsigned long) buf + size,
.user_cookie = cookie,
};
if (ioctl(umn_fd, UMMUNOT_REGISTER_REGION, &r)) {
perror("ioctl");
return 1;
}
return 0;
}
static int umn_unregister(__u64 cookie)
{
if (ioctl(umn_fd, UMMUNOT_UNREGISTER_REGION, &cookie)) {
perror("ioctl");
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
int page_size = sysconf(_SC_PAGESIZE);
void *t;
if (umn_init())
return 1;
if (*umn_counter != 0) {
fprintf(stderr, "counter = %lld (expected 0)\n", *umn_counter);
return 1;
}
t = mmap(NULL, 3 * page_size, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
if (umn_register(t, 3 * page_size, 123))
return 1;
munmap(t + page_size, page_size);
printf("ummunot events: %lld\n", *umn_counter);
if (*umn_counter > 0) {
struct ummunot_event ev[2];
int len;
int i;
len = read(umn_fd, &ev, sizeof ev);
printf("read %d events (%d tot)\n", len / sizeof ev[0], len);
for (i = 0; i < len / sizeof ev[0]; ++i) {
switch (ev[i].type) {
case UMMUNOT_EVENT_TYPE_INVAL:
printf("[%3d]: inval cookie %lld\n",
i, ev[i].user_cookie_counter);
if (ev[i].flags & UMMUNOT_EVENT_FLAG_HINT)
printf(" hint %llx...%lx\n",
ev[i].hint_start, ev[i].hint_end);
break;
case UMMUNOT_EVENT_TYPE_LAST:
printf("[%3d]: empty up to %lld\n",
i, ev[i].user_cookie_counter);
break;
default:
printf("[%3d]: unknown event type %d\n",
i, ev[i].type);
break;
}
}
}
umn_unregister(123);
munmap(t, page_size);
printf("ummunot events: %lld\n", *umn_counter);
return 0;
}
More information about the general
mailing list