From abec512883a03d4b9e7136fd7db1127c7d6317c9 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Fri, 1 Nov 2019 02:38:45 +0100 Subject: [PATCH] input: use ro_anonymous_file to minimize duplication of keymap files Since version 7 clients must use MAP_PRIVATE to map the keymap fd so we can use memfd_create in os_ro_anonymous_file_get_ref using RO_ANONYMOUS_FILE_MAPMODE_PRIVATE, for older version we use RO_ANONYMOUS_FILE_MAPMODE_SHARED to be compatibile with MAP_SHARED. Signed-off-by: Sebastian Wick --- include/libweston/libweston.h | 4 +-- libweston/input.c | 55 ++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 1eab33af..e914d6a3 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -78,6 +78,7 @@ struct weston_pointer; struct linux_dmabuf_buffer; struct weston_recorder; struct weston_pointer_constraint; +struct ro_anonymous_file; enum weston_keyboard_modifier { MODIFIER_CTRL = (1 << 0), @@ -704,8 +705,7 @@ weston_pointer_start_drag(struct weston_pointer *pointer, struct wl_client *client); struct weston_xkb_info { struct xkb_keymap *keymap; - size_t keymap_size; - char *keymap_string; + struct ro_anonymous_file *keymap_rofile; int32_t ref_count; xkb_mod_index_t shift_mod; xkb_mod_index_t caps_mod; diff --git a/libweston/input.c b/libweston/input.c index 1df596fc..28dcb0b9 100644 --- a/libweston/input.c +++ b/libweston/input.c @@ -2086,32 +2086,30 @@ WL_EXPORT void weston_keyboard_send_keymap(struct weston_keyboard *kbd, struct wl_resource *resource) { struct weston_xkb_info *xkb_info = kbd->xkb_info; - void *area; int fd; + size_t size; + enum ro_anonymous_file_mapmode mapmode; - fd = os_create_anonymous_file(xkb_info->keymap_size); - if (fd < 0) { - weston_log("creating a keymap file for %lu bytes failed: %s\n", - (unsigned long) xkb_info->keymap_size, + if (wl_resource_get_version(resource) < 7) + mapmode = RO_ANONYMOUS_FILE_MAPMODE_SHARED; + else + mapmode = RO_ANONYMOUS_FILE_MAPMODE_PRIVATE; + + fd = os_ro_anonymous_file_get_fd(xkb_info->keymap_rofile, mapmode); + size = os_ro_anonymous_file_size(xkb_info->keymap_rofile); + + if (fd == -1) { + weston_log("creating a keymap file failed: %s\n", strerror(errno)); return; } - area = mmap(NULL, xkb_info->keymap_size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (area == MAP_FAILED) { - weston_log("failed to mmap() %lu bytes\n", - (unsigned long) xkb_info->keymap_size); - goto err_mmap; - } - strcpy(area, xkb_info->keymap_string); - munmap(area, xkb_info->keymap_size); wl_keyboard_send_keymap(resource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, - xkb_info->keymap_size); -err_mmap: - close(fd); + size); + + os_ro_anonymous_file_put_fd(fd); } static void @@ -3149,8 +3147,7 @@ weston_xkb_info_destroy(struct weston_xkb_info *xkb_info) xkb_keymap_unref(xkb_info->keymap); - if (xkb_info->keymap_string) - free(xkb_info->keymap_string); + os_ro_anonymous_file_destroy(xkb_info->keymap_rofile); free(xkb_info); } @@ -3171,6 +3168,8 @@ weston_compositor_xkb_destroy(struct weston_compositor *ec) static struct weston_xkb_info * weston_xkb_info_create(struct xkb_keymap *keymap) { + char *keymap_string; + size_t keymap_size; struct weston_xkb_info *xkb_info = zalloc(sizeof *xkb_info); if (xkb_info == NULL) return NULL; @@ -3202,13 +3201,22 @@ weston_xkb_info_create(struct xkb_keymap *keymap) xkb_info->scroll_led = xkb_keymap_led_get_index(xkb_info->keymap, XKB_LED_NAME_SCROLL); - xkb_info->keymap_string = xkb_keymap_get_as_string(xkb_info->keymap, + keymap_string = xkb_keymap_get_as_string(xkb_info->keymap, XKB_KEYMAP_FORMAT_TEXT_V1); - if (xkb_info->keymap_string == NULL) { + if (keymap_string == NULL) { weston_log("failed to get string version of keymap\n"); goto err_keymap; } - xkb_info->keymap_size = strlen(xkb_info->keymap_string) + 1; + keymap_size = strlen(keymap_string) + 1; + + xkb_info->keymap_rofile = os_ro_anonymous_file_create(keymap_size, + keymap_string); + free(keymap_string); + + if (!xkb_info->keymap_rofile) { + weston_log("failed to create anonymous file for keymap\n"); + goto err_keymap; + } return xkb_info; @@ -3441,7 +3449,8 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec, wl_signal_init(&seat->destroy_signal); wl_signal_init(&seat->updated_caps_signal); - seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 7, + seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, + MIN(wl_seat_interface.version, 7), seat, bind_seat); seat->compositor = ec;