From owner-dev-commits-src-branches@freebsd.org Sat May 1 00:39:01 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id B1FD362E4FF; Sat, 1 May 2021 00:39:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4FX9N53gZLz3pm5; Sat, 1 May 2021 00:39:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 6D6EA5D43; Sat, 1 May 2021 00:39:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 1410d1Zt048059; Sat, 1 May 2021 00:39:01 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 1410d1P5048058; Sat, 1 May 2021 00:39:01 GMT (envelope-from git) Date: Sat, 1 May 2021 00:39:01 GMT Message-Id: <202105010039.1410d1P5048058@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Konstantin Belousov Subject: git: e35c16556617 - stable/12 - linuxkpi: remove erronously committed diff save file MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/stable/12 X-Git-Reftype: branch X-Git-Commit: e35c16556617eab9e922686f7760c1f1cf3cea5b Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 01 May 2021 00:39:02 -0000 The branch stable/12 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=e35c16556617eab9e922686f7760c1f1cf3cea5b commit e35c16556617eab9e922686f7760c1f1cf3cea5b Author: Konstantin Belousov AuthorDate: 2021-04-06 00:42:13 +0000 Commit: Konstantin Belousov CommitDate: 2021-05-01 00:38:29 +0000 linuxkpi: remove erronously committed diff save file (cherry picked from commit 5b3b19db7305f8255f021d6f8d94d17ab778660f) --- sys/compat/linuxkpi/common/src/linux_compat.c.orig | 2615 -------------------- 1 file changed, 2615 deletions(-) diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c.orig b/sys/compat/linuxkpi/common/src/linux_compat.c.orig deleted file mode 100644 index 28413c59bb76..000000000000 --- a/sys/compat/linuxkpi/common/src/linux_compat.c.orig +++ /dev/null @@ -1,2615 +0,0 @@ -/*- - * Copyright (c) 2010 Isilon Systems, Inc. - * Copyright (c) 2010 iX Systems, Inc. - * Copyright (c) 2010 Panasas, Inc. - * Copyright (c) 2013-2018 Mellanox Technologies, Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_stack.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#if defined(__i386__) || defined(__amd64__) -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__i386__) || defined(__amd64__) -#include -#endif - -SYSCTL_NODE(_compat, OID_AUTO, linuxkpi, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, - "LinuxKPI parameters"); - -int linuxkpi_debug; -SYSCTL_INT(_compat_linuxkpi, OID_AUTO, debug, CTLFLAG_RWTUN, - &linuxkpi_debug, 0, "Set to enable pr_debug() prints. Clear to disable."); - -static struct timeval lkpi_net_lastlog; -static int lkpi_net_curpps; -static int lkpi_net_maxpps = 99; -SYSCTL_INT(_compat_linuxkpi, OID_AUTO, net_ratelimit, CTLFLAG_RWTUN, - &lkpi_net_maxpps, 0, "Limit number of LinuxKPI net messages per second."); - -MALLOC_DEFINE(M_KMALLOC, "linux", "Linux kmalloc compat"); - -#include -/* Undo Linux compat changes. */ -#undef RB_ROOT -#undef file -#undef cdev -#define RB_ROOT(head) (head)->rbh_root - -static void linux_cdev_deref(struct linux_cdev *ldev); -static struct vm_area_struct *linux_cdev_handle_find(void *handle); - -struct kobject linux_class_root; -struct device linux_root_device; -struct class linux_class_misc; -struct list_head pci_drivers; -struct list_head pci_devices; -spinlock_t pci_lock; - -unsigned long linux_timer_hz_mask; - -wait_queue_head_t linux_bit_waitq; -wait_queue_head_t linux_var_waitq; - -int -panic_cmp(struct rb_node *one, struct rb_node *two) -{ - panic("no cmp"); -} - -RB_GENERATE(linux_root, rb_node, __entry, panic_cmp); - -int -kobject_set_name_vargs(struct kobject *kobj, const char *fmt, va_list args) -{ - va_list tmp_va; - int len; - char *old; - char *name; - char dummy; - - old = kobj->name; - - if (old && fmt == NULL) - return (0); - - /* compute length of string */ - va_copy(tmp_va, args); - len = vsnprintf(&dummy, 0, fmt, tmp_va); - va_end(tmp_va); - - /* account for zero termination */ - len++; - - /* check for error */ - if (len < 1) - return (-EINVAL); - - /* allocate memory for string */ - name = kzalloc(len, GFP_KERNEL); - if (name == NULL) - return (-ENOMEM); - vsnprintf(name, len, fmt, args); - kobj->name = name; - - /* free old string */ - kfree(old); - - /* filter new string */ - for (; *name != '\0'; name++) - if (*name == '/') - *name = '!'; - return (0); -} - -int -kobject_set_name(struct kobject *kobj, const char *fmt, ...) -{ - va_list args; - int error; - - va_start(args, fmt); - error = kobject_set_name_vargs(kobj, fmt, args); - va_end(args); - - return (error); -} - -static int -kobject_add_complete(struct kobject *kobj, struct kobject *parent) -{ - const struct kobj_type *t; - int error; - - kobj->parent = parent; - error = sysfs_create_dir(kobj); - if (error == 0 && kobj->ktype && kobj->ktype->default_attrs) { - struct attribute **attr; - t = kobj->ktype; - - for (attr = t->default_attrs; *attr != NULL; attr++) { - error = sysfs_create_file(kobj, *attr); - if (error) - break; - } - if (error) - sysfs_remove_dir(kobj); - } - return (error); -} - -int -kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...) -{ - va_list args; - int error; - - va_start(args, fmt); - error = kobject_set_name_vargs(kobj, fmt, args); - va_end(args); - if (error) - return (error); - - return kobject_add_complete(kobj, parent); -} - -void -linux_kobject_release(struct kref *kref) -{ - struct kobject *kobj; - char *name; - - kobj = container_of(kref, struct kobject, kref); - sysfs_remove_dir(kobj); - name = kobj->name; - if (kobj->ktype && kobj->ktype->release) - kobj->ktype->release(kobj); - kfree(name); -} - -static void -linux_kobject_kfree(struct kobject *kobj) -{ - kfree(kobj); -} - -static void -linux_kobject_kfree_name(struct kobject *kobj) -{ - if (kobj) { - kfree(kobj->name); - } -} - -const struct kobj_type linux_kfree_type = { - .release = linux_kobject_kfree -}; - -static void -linux_device_release(struct device *dev) -{ - pr_debug("linux_device_release: %s\n", dev_name(dev)); - kfree(dev); -} - -static ssize_t -linux_class_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct class_attribute *dattr; - ssize_t error; - - dattr = container_of(attr, struct class_attribute, attr); - error = -EIO; - if (dattr->show) - error = dattr->show(container_of(kobj, struct class, kobj), - dattr, buf); - return (error); -} - -static ssize_t -linux_class_store(struct kobject *kobj, struct attribute *attr, const char *buf, - size_t count) -{ - struct class_attribute *dattr; - ssize_t error; - - dattr = container_of(attr, struct class_attribute, attr); - error = -EIO; - if (dattr->store) - error = dattr->store(container_of(kobj, struct class, kobj), - dattr, buf, count); - return (error); -} - -static void -linux_class_release(struct kobject *kobj) -{ - struct class *class; - - class = container_of(kobj, struct class, kobj); - if (class->class_release) - class->class_release(class); -} - -static const struct sysfs_ops linux_class_sysfs = { - .show = linux_class_show, - .store = linux_class_store, -}; - -const struct kobj_type linux_class_ktype = { - .release = linux_class_release, - .sysfs_ops = &linux_class_sysfs -}; - -static void -linux_dev_release(struct kobject *kobj) -{ - struct device *dev; - - dev = container_of(kobj, struct device, kobj); - /* This is the precedence defined by linux. */ - if (dev->release) - dev->release(dev); - else if (dev->class && dev->class->dev_release) - dev->class->dev_release(dev); -} - -static ssize_t -linux_dev_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct device_attribute *dattr; - ssize_t error; - - dattr = container_of(attr, struct device_attribute, attr); - error = -EIO; - if (dattr->show) - error = dattr->show(container_of(kobj, struct device, kobj), - dattr, buf); - return (error); -} - -static ssize_t -linux_dev_store(struct kobject *kobj, struct attribute *attr, const char *buf, - size_t count) -{ - struct device_attribute *dattr; - ssize_t error; - - dattr = container_of(attr, struct device_attribute, attr); - error = -EIO; - if (dattr->store) - error = dattr->store(container_of(kobj, struct device, kobj), - dattr, buf, count); - return (error); -} - -static const struct sysfs_ops linux_dev_sysfs = { - .show = linux_dev_show, - .store = linux_dev_store, -}; - -const struct kobj_type linux_dev_ktype = { - .release = linux_dev_release, - .sysfs_ops = &linux_dev_sysfs -}; - -struct device * -device_create(struct class *class, struct device *parent, dev_t devt, - void *drvdata, const char *fmt, ...) -{ - struct device *dev; - va_list args; - - dev = kzalloc(sizeof(*dev), M_WAITOK); - dev->parent = parent; - dev->class = class; - dev->devt = devt; - dev->driver_data = drvdata; - dev->release = linux_device_release; - va_start(args, fmt); - kobject_set_name_vargs(&dev->kobj, fmt, args); - va_end(args); - device_register(dev); - - return (dev); -} - -int -kobject_init_and_add(struct kobject *kobj, const struct kobj_type *ktype, - struct kobject *parent, const char *fmt, ...) -{ - va_list args; - int error; - - kobject_init(kobj, ktype); - kobj->ktype = ktype; - kobj->parent = parent; - kobj->name = NULL; - - va_start(args, fmt); - error = kobject_set_name_vargs(kobj, fmt, args); - va_end(args); - if (error) - return (error); - return kobject_add_complete(kobj, parent); -} - -static void -linux_kq_lock(void *arg) -{ - spinlock_t *s = arg; - - spin_lock(s); -} -static void -linux_kq_unlock(void *arg) -{ - spinlock_t *s = arg; - - spin_unlock(s); -} - -static void -linux_kq_assert_lock(void *arg, int what) -{ -#ifdef INVARIANTS - spinlock_t *s = arg; - - if (what == LA_LOCKED) - mtx_assert(&s->m, MA_OWNED); - else - mtx_assert(&s->m, MA_NOTOWNED); -#endif -} - -static void -linux_file_kqfilter_poll(struct linux_file *, int); - -struct linux_file * -linux_file_alloc(void) -{ - struct linux_file *filp; - - filp = kzalloc(sizeof(*filp), GFP_KERNEL); - - /* set initial refcount */ - filp->f_count = 1; - - /* setup fields needed by kqueue support */ - spin_lock_init(&filp->f_kqlock); - knlist_init(&filp->f_selinfo.si_note, &filp->f_kqlock, - linux_kq_lock, linux_kq_unlock, linux_kq_assert_lock); - - return (filp); -} - -void -linux_file_free(struct linux_file *filp) -{ - if (filp->_file == NULL) { - if (filp->f_shmem != NULL) - vm_object_deallocate(filp->f_shmem); - kfree(filp); - } else { - /* - * The close method of the character device or file - * will free the linux_file structure: - */ - _fdrop(filp->_file, curthread); - } -} - -static int -linux_cdev_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot, - vm_page_t *mres) -{ - struct vm_area_struct *vmap; - - vmap = linux_cdev_handle_find(vm_obj->handle); - - MPASS(vmap != NULL); - MPASS(vmap->vm_private_data == vm_obj->handle); - - if (likely(vmap->vm_ops != NULL && offset < vmap->vm_len)) { - vm_paddr_t paddr = IDX_TO_OFF(vmap->vm_pfn) + offset; - vm_page_t page; - - if (((*mres)->flags & PG_FICTITIOUS) != 0) { - /* - * If the passed in result page is a fake - * page, update it with the new physical - * address. - */ - page = *mres; - vm_page_updatefake(page, paddr, vm_obj->memattr); - } else { - /* - * Replace the passed in "mres" page with our - * own fake page and free up the all of the - * original pages. - */ - VM_OBJECT_WUNLOCK(vm_obj); - page = vm_page_getfake(paddr, vm_obj->memattr); - VM_OBJECT_WLOCK(vm_obj); - - vm_page_replace(page, vm_obj, (*mres)->pindex, *mres); - *mres = page; - } - vm_page_valid(page); - return (VM_PAGER_OK); - } - return (VM_PAGER_FAIL); -} - -static int -linux_cdev_pager_populate(vm_object_t vm_obj, vm_pindex_t pidx, int fault_type, - vm_prot_t max_prot, vm_pindex_t *first, vm_pindex_t *last) -{ - struct vm_area_struct *vmap; - int err; - - /* get VM area structure */ - vmap = linux_cdev_handle_find(vm_obj->handle); - MPASS(vmap != NULL); - MPASS(vmap->vm_private_data == vm_obj->handle); - - VM_OBJECT_WUNLOCK(vm_obj); - - linux_set_current(curthread); - - down_write(&vmap->vm_mm->mmap_sem); - if (unlikely(vmap->vm_ops == NULL)) { - err = VM_FAULT_SIGBUS; - } else { - struct vm_fault vmf; - - /* fill out VM fault structure */ - vmf.virtual_address = (void *)(uintptr_t)IDX_TO_OFF(pidx); - vmf.flags = (fault_type & VM_PROT_WRITE) ? FAULT_FLAG_WRITE : 0; - vmf.pgoff = 0; - vmf.page = NULL; - vmf.vma = vmap; - - vmap->vm_pfn_count = 0; - vmap->vm_pfn_pcount = &vmap->vm_pfn_count; - vmap->vm_obj = vm_obj; - - err = vmap->vm_ops->fault(vmap, &vmf); - - while (vmap->vm_pfn_count == 0 && err == VM_FAULT_NOPAGE) { - kern_yield(PRI_USER); - err = vmap->vm_ops->fault(vmap, &vmf); - } - } - - /* translate return code */ - switch (err) { - case VM_FAULT_OOM: - err = VM_PAGER_AGAIN; - break; - case VM_FAULT_SIGBUS: - err = VM_PAGER_BAD; - break; - case VM_FAULT_NOPAGE: - /* - * By contract the fault handler will return having - * busied all the pages itself. If pidx is already - * found in the object, it will simply xbusy the first - * page and return with vm_pfn_count set to 1. - */ - *first = vmap->vm_pfn_first; - *last = *first + vmap->vm_pfn_count - 1; - err = VM_PAGER_OK; - break; - default: - err = VM_PAGER_ERROR; - break; - } - up_write(&vmap->vm_mm->mmap_sem); - VM_OBJECT_WLOCK(vm_obj); - return (err); -} - -static struct rwlock linux_vma_lock; -static TAILQ_HEAD(, vm_area_struct) linux_vma_head = - TAILQ_HEAD_INITIALIZER(linux_vma_head); - -static void -linux_cdev_handle_free(struct vm_area_struct *vmap) -{ - /* Drop reference on vm_file */ - if (vmap->vm_file != NULL) - fput(vmap->vm_file); - - /* Drop reference on mm_struct */ - mmput(vmap->vm_mm); - - kfree(vmap); -} - -static void -linux_cdev_handle_remove(struct vm_area_struct *vmap) -{ - rw_wlock(&linux_vma_lock); - TAILQ_REMOVE(&linux_vma_head, vmap, vm_entry); - rw_wunlock(&linux_vma_lock); -} - -static struct vm_area_struct * -linux_cdev_handle_find(void *handle) -{ - struct vm_area_struct *vmap; - - rw_rlock(&linux_vma_lock); - TAILQ_FOREACH(vmap, &linux_vma_head, vm_entry) { - if (vmap->vm_private_data == handle) - break; - } - rw_runlock(&linux_vma_lock); - return (vmap); -} - -static int -linux_cdev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, - vm_ooffset_t foff, struct ucred *cred, u_short *color) -{ - - MPASS(linux_cdev_handle_find(handle) != NULL); - *color = 0; - return (0); -} - -static void -linux_cdev_pager_dtor(void *handle) -{ - const struct vm_operations_struct *vm_ops; - struct vm_area_struct *vmap; - - vmap = linux_cdev_handle_find(handle); - MPASS(vmap != NULL); - - /* - * Remove handle before calling close operation to prevent - * other threads from reusing the handle pointer. - */ - linux_cdev_handle_remove(vmap); - - down_write(&vmap->vm_mm->mmap_sem); - vm_ops = vmap->vm_ops; - if (likely(vm_ops != NULL)) - vm_ops->close(vmap); - up_write(&vmap->vm_mm->mmap_sem); - - linux_cdev_handle_free(vmap); -} - -static struct cdev_pager_ops linux_cdev_pager_ops[2] = { - { - /* OBJT_MGTDEVICE */ - .cdev_pg_populate = linux_cdev_pager_populate, - .cdev_pg_ctor = linux_cdev_pager_ctor, - .cdev_pg_dtor = linux_cdev_pager_dtor - }, - { - /* OBJT_DEVICE */ - .cdev_pg_fault = linux_cdev_pager_fault, - .cdev_pg_ctor = linux_cdev_pager_ctor, - .cdev_pg_dtor = linux_cdev_pager_dtor - }, -}; - -int -zap_vma_ptes(struct vm_area_struct *vma, unsigned long address, - unsigned long size) -{ - vm_object_t obj; - vm_page_t m; - - obj = vma->vm_obj; - if (obj == NULL || (obj->flags & OBJ_UNMANAGED) != 0) - return (-ENOTSUP); - VM_OBJECT_RLOCK(obj); - for (m = vm_page_find_least(obj, OFF_TO_IDX(address)); - m != NULL && m->pindex < OFF_TO_IDX(address + size); - m = TAILQ_NEXT(m, listq)) - pmap_remove_all(m); - VM_OBJECT_RUNLOCK(obj); - return (0); -} - -static struct file_operations dummy_ldev_ops = { - /* XXXKIB */ -}; - -static struct linux_cdev dummy_ldev = { - .ops = &dummy_ldev_ops, -}; - -#define LDEV_SI_DTR 0x0001 -#define LDEV_SI_REF 0x0002 - -static void -linux_get_fop(struct linux_file *filp, const struct file_operations **fop, - struct linux_cdev **dev) -{ - struct linux_cdev *ldev; - u_int siref; - - ldev = filp->f_cdev; - *fop = filp->f_op; - if (ldev != NULL) { - if (ldev->kobj.ktype == &linux_cdev_static_ktype) { - refcount_acquire(&ldev->refs); - } else { - for (siref = ldev->siref;;) { - if ((siref & LDEV_SI_DTR) != 0) { - ldev = &dummy_ldev; - *fop = ldev->ops; - siref = ldev->siref; - MPASS((ldev->siref & LDEV_SI_DTR) == 0); - } else if (atomic_fcmpset_int(&ldev->siref, - &siref, siref + LDEV_SI_REF)) { - break; - } - } - } - } - *dev = ldev; -} - -static void -linux_drop_fop(struct linux_cdev *ldev) -{ - - if (ldev == NULL) - return; - if (ldev->kobj.ktype == &linux_cdev_static_ktype) { - linux_cdev_deref(ldev); - } else { - MPASS(ldev->kobj.ktype == &linux_cdev_ktype); - MPASS((ldev->siref & ~LDEV_SI_DTR) != 0); - atomic_subtract_int(&ldev->siref, LDEV_SI_REF); - } -} - -#define OPW(fp,td,code) ({ \ - struct file *__fpop; \ - __typeof(code) __retval; \ - \ - __fpop = (td)->td_fpop; \ - (td)->td_fpop = (fp); \ - __retval = (code); \ - (td)->td_fpop = __fpop; \ - __retval; \ -}) - -static int -linux_dev_fdopen(struct cdev *dev, int fflags, struct thread *td, - struct file *file) -{ - struct linux_cdev *ldev; - struct linux_file *filp; - const struct file_operations *fop; - int error; - - ldev = dev->si_drv1; - - filp = linux_file_alloc(); - filp->f_dentry = &filp->f_dentry_store; - filp->f_op = ldev->ops; - filp->f_mode = file->f_flag; - filp->f_flags = file->f_flag; - filp->f_vnode = file->f_vnode; - filp->_file = file; - refcount_acquire(&ldev->refs); - filp->f_cdev = ldev; - - linux_set_current(td); - linux_get_fop(filp, &fop, &ldev); - - if (fop->open != NULL) { - error = -fop->open(file->f_vnode, filp); - if (error != 0) { - linux_drop_fop(ldev); - linux_cdev_deref(filp->f_cdev); - kfree(filp); - return (error); - } - } - - /* hold on to the vnode - used for fstat() */ - vhold(filp->f_vnode); - - /* release the file from devfs */ - finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops); - linux_drop_fop(ldev); - return (ENXIO); -} - -#define LINUX_IOCTL_MIN_PTR 0x10000UL -#define LINUX_IOCTL_MAX_PTR (LINUX_IOCTL_MIN_PTR + IOCPARM_MAX) - -static inline int -linux_remap_address(void **uaddr, size_t len) -{ - uintptr_t uaddr_val = (uintptr_t)(*uaddr); - - if (unlikely(uaddr_val >= LINUX_IOCTL_MIN_PTR && - uaddr_val < LINUX_IOCTL_MAX_PTR)) { - struct task_struct *pts = current; - if (pts == NULL) { - *uaddr = NULL; - return (1); - } - - /* compute data offset */ - uaddr_val -= LINUX_IOCTL_MIN_PTR; - - /* check that length is within bounds */ - if ((len > IOCPARM_MAX) || - (uaddr_val + len) > pts->bsd_ioctl_len) { - *uaddr = NULL; - return (1); - } - - /* re-add kernel buffer address */ - uaddr_val += (uintptr_t)pts->bsd_ioctl_data; - - /* update address location */ - *uaddr = (void *)uaddr_val; - return (1); - } - return (0); -} - -int -linux_copyin(const void *uaddr, void *kaddr, size_t len) -{ - if (linux_remap_address(__DECONST(void **, &uaddr), len)) { - if (uaddr == NULL) - return (-EFAULT); - memcpy(kaddr, uaddr, len); - return (0); - } - return (-copyin(uaddr, kaddr, len)); -} - -int -linux_copyout(const void *kaddr, void *uaddr, size_t len) -{ - if (linux_remap_address(&uaddr, len)) { - if (uaddr == NULL) - return (-EFAULT); - memcpy(uaddr, kaddr, len); - return (0); - } - return (-copyout(kaddr, uaddr, len)); -} - -size_t -linux_clear_user(void *_uaddr, size_t _len) -{ - uint8_t *uaddr = _uaddr; - size_t len = _len; - - /* make sure uaddr is aligned before going into the fast loop */ - while (((uintptr_t)uaddr & 7) != 0 && len > 7) { - if (subyte(uaddr, 0)) - return (_len); - uaddr++; - len--; - } - - /* zero 8 bytes at a time */ - while (len > 7) { -#ifdef __LP64__ - if (suword64(uaddr, 0)) - return (_len); -#else - if (suword32(uaddr, 0)) - return (_len); - if (suword32(uaddr + 4, 0)) - return (_len); -#endif - uaddr += 8; - len -= 8; - } - - /* zero fill end, if any */ - while (len > 0) { - if (subyte(uaddr, 0)) - return (_len); - uaddr++; - len--; - } - return (0); -} - -int -linux_access_ok(const void *uaddr, size_t len) -{ - uintptr_t saddr; - uintptr_t eaddr; - - /* get start and end address */ - saddr = (uintptr_t)uaddr; - eaddr = (uintptr_t)uaddr + len; - - /* verify addresses are valid for userspace */ - return ((saddr == eaddr) || - (eaddr > saddr && eaddr <= VM_MAXUSER_ADDRESS)); -} - -/* - * This function should return either EINTR or ERESTART depending on - * the signal type sent to this thread: - */ -static int -linux_get_error(struct task_struct *task, int error) -{ - /* check for signal type interrupt code */ - if (error == EINTR || error == ERESTARTSYS || error == ERESTART) { - error = -linux_schedule_get_interrupt_value(task); - if (error == 0) - error = EINTR; - } - return (error); -} - -static int -linux_file_ioctl_sub(struct file *fp, struct linux_file *filp, - const struct file_operations *fop, u_long cmd, caddr_t data, - struct thread *td) -{ - struct task_struct *task = current; - unsigned size; - int error; - - size = IOCPARM_LEN(cmd); - /* refer to logic in sys_ioctl() */ - if (size > 0) { - /* - * Setup hint for linux_copyin() and linux_copyout(). - * - * Background: Linux code expects a user-space address - * while FreeBSD supplies a kernel-space address. - */ - task->bsd_ioctl_data = data; - task->bsd_ioctl_len = size; - data = (void *)LINUX_IOCTL_MIN_PTR; - } else { - /* fetch user-space pointer */ - data = *(void **)data; - } -#if defined(__amd64__) - if (td->td_proc->p_elf_machine == EM_386) { *** 1651 LINES SKIPPED ***