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