input: use ro_anonymous_file to minimize duplication of keymap files
authorSebastian Wick <sebastian@sebastianwick.net>
Fri, 1 Nov 2019 01:38:45 +0000 (02:38 +0100)
committerSebastian Wick <sebastian@sebastianwick.net>
Mon, 4 Nov 2019 14:10:05 +0000 (15:10 +0100)
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 <sebastian@sebastianwick.net>
include/libweston/libweston.h
libweston/input.c

index 1eab33af51d39219bb911d587db598b74f358b63..e914d6a30d53cd1da9b73261b316a6d5e6a25a0a 100644 (file)
@@ -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;
index 1df596fc03290ff9e75b88603f4a0c731db348b6..28dcb0b9a847d2769e6404ca78685f270979970b 100644 (file)
@@ -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;