svn commit: r323703 - in head/sys/compat/linuxkpi/common: include/linux src
Hans Petter Selasky
hselasky at FreeBSD.org
Mon Sep 18 13:17:25 UTC 2017
Author: hselasky
Date: Mon Sep 18 13:17:23 2017
New Revision: 323703
URL: https://svnweb.freebsd.org/changeset/base/323703
Log:
Add support for shared memory functions to the LinuxKPI.
Obtained from: kmacy @
MFC after: 1 week
Sponsored by: Mellanox Technologies
Modified:
head/sys/compat/linuxkpi/common/include/linux/fs.h
head/sys/compat/linuxkpi/common/src/linux_page.c
Modified: head/sys/compat/linuxkpi/common/include/linux/fs.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/fs.h Mon Sep 18 08:46:07 2017 (r323702)
+++ head/sys/compat/linuxkpi/common/include/linux/fs.h Mon Sep 18 13:17:23 2017 (r323703)
@@ -2,7 +2,7 @@
* Copyright (c) 2010 Isilon Systems, Inc.
* Copyright (c) 2010 iX Systems, Inc.
* Copyright (c) 2010 Panasas, Inc.
- * Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
+ * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -287,5 +287,26 @@ noop_llseek(struct linux_file *file, loff_t offset, in
return (file->_file->f_offset);
}
+
+/* Shared memory support */
+unsigned long linux_invalidate_mapping_pages(vm_object_t, pgoff_t, pgoff_t);
+struct page *linux_shmem_read_mapping_page_gfp(vm_object_t, int, gfp_t);
+struct linux_file *linux_shmem_file_setup(const char *, loff_t, unsigned long);
+void linux_shmem_truncate_range(vm_object_t, loff_t, loff_t);
+
+#define invalidate_mapping_pages(...) \
+ linux_invalidate_mapping_pages(__VA_ARGS__)
+
+#define shmem_read_mapping_page(...) \
+ linux_shmem_read_mapping_page_gfp(__VA_ARGS__, 0)
+
+#define shmem_read_mapping_page_gfp(...) \
+ linux_shmem_read_mapping_page_gfp(__VA_ARGS__)
+
+#define shmem_file_setup(...) \
+ linux_shmem_file_setup(__VA_ARGS__)
+
+#define shmem_truncate_range(...) \
+ linux_shmem_truncate_range(__VA_ARGS__)
#endif /* _LINUX_FS_H_ */
Modified: head/sys/compat/linuxkpi/common/src/linux_page.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_page.c Mon Sep 18 08:46:07 2017 (r323702)
+++ head/sys/compat/linuxkpi/common/src/linux_page.c Mon Sep 18 13:17:23 2017 (r323703)
@@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <linux/gfp.h>
#include <linux/mm.h>
#include <linux/preempt.h>
+#include <linux/fs.h>
#if defined(__amd64__) || defined(__aarch64__) || defined(__riscv)
#define LINUXKPI_HAVE_DMAP
@@ -288,4 +289,108 @@ int
is_vmalloc_addr(const void *addr)
{
return (vtoslab((vm_offset_t)addr & ~UMA_SLAB_MASK) != NULL);
+}
+
+struct page *
+linux_shmem_read_mapping_page_gfp(vm_object_t obj, int pindex, gfp_t gfp)
+{
+ vm_page_t page;
+ int rv;
+
+ if ((gfp & GFP_NOWAIT) != 0)
+ panic("GFP_NOWAIT is unimplemented");
+
+ VM_OBJECT_WLOCK(obj);
+ page = vm_page_grab(obj, pindex, VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY |
+ VM_ALLOC_WIRED);
+ if (page->valid != VM_PAGE_BITS_ALL) {
+ vm_page_xbusy(page);
+ if (vm_pager_has_page(obj, pindex, NULL, NULL)) {
+ rv = vm_pager_get_pages(obj, &page, 1, NULL, NULL);
+ if (rv != VM_PAGER_OK) {
+ vm_page_lock(page);
+ vm_page_unwire(page, PQ_NONE);
+ vm_page_free(page);
+ vm_page_unlock(page);
+ VM_OBJECT_WUNLOCK(obj);
+ return (ERR_PTR(-EINVAL));
+ }
+ MPASS(page->valid == VM_PAGE_BITS_ALL);
+ } else {
+ pmap_zero_page(page);
+ page->valid = VM_PAGE_BITS_ALL;
+ page->dirty = 0;
+ }
+ vm_page_xunbusy(page);
+ }
+ vm_page_lock(page);
+ vm_page_hold(page);
+ vm_page_unlock(page);
+ VM_OBJECT_WUNLOCK(obj);
+ return (page);
+}
+
+struct linux_file *
+linux_shmem_file_setup(const char *name, loff_t size, unsigned long flags)
+{
+ struct fileobj {
+ struct linux_file file __aligned(sizeof(void *));
+ struct vnode vnode __aligned(sizeof(void *));
+ };
+ struct fileobj *fileobj;
+ struct linux_file *filp;
+ struct vnode *vp;
+ int error;
+
+ fileobj = kzalloc(sizeof(*fileobj), GFP_KERNEL);
+ if (fileobj == NULL) {
+ error = -ENOMEM;
+ goto err_0;
+ }
+ filp = &fileobj->file;
+ vp = &fileobj->vnode;
+
+ filp->f_count = 1;
+ filp->f_vnode = vp;
+ filp->f_shmem = vm_pager_allocate(OBJT_DEFAULT, NULL, size,
+ VM_PROT_READ | VM_PROT_WRITE, 0, curthread->td_ucred);
+ if (filp->f_shmem == NULL) {
+ error = -ENOMEM;
+ goto err_1;
+ }
+ return (filp);
+err_1:
+ kfree(filp);
+err_0:
+ return (ERR_PTR(error));
+}
+
+static vm_ooffset_t
+linux_invalidate_mapping_pages_sub(vm_object_t obj, vm_pindex_t start,
+ vm_pindex_t end, int flags)
+{
+ int start_count, end_count;
+
+ VM_OBJECT_WLOCK(obj);
+ start_count = obj->resident_page_count;
+ vm_object_page_remove(obj, start, end, flags);
+ end_count = obj->resident_page_count;
+ VM_OBJECT_WUNLOCK(obj);
+ return (start_count - end_count);
+}
+
+unsigned long
+linux_invalidate_mapping_pages(vm_object_t obj, pgoff_t start, pgoff_t end)
+{
+
+ return (linux_invalidate_mapping_pages_sub(obj, start, end, OBJPR_CLEANONLY));
+}
+
+void
+linux_shmem_truncate_range(vm_object_t obj, loff_t lstart, loff_t lend)
+{
+ vm_pindex_t start = OFF_TO_IDX(lstart + PAGE_SIZE - 1);
+ vm_pindex_t end = OFF_TO_IDX(lend + 1);
+
+ (void) linux_invalidate_mapping_pages_sub(obj, start, end, 0);
}
More information about the svn-src-head
mailing list