From owner-svn-src-head@freebsd.org Sat Feb 23 20:56:42 2019 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 9DBF31505879; Sat, 23 Feb 2019 20:56:42 +0000 (UTC) (envelope-from mmacy@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) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 1DFA96F31F; Sat, 23 Feb 2019 20:56:42 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 1134F22A65; Sat, 23 Feb 2019 20:56:42 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x1NKugPG075480; Sat, 23 Feb 2019 20:56:42 GMT (envelope-from mmacy@FreeBSD.org) Received: (from mmacy@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x1NKufKt075476; Sat, 23 Feb 2019 20:56:41 GMT (envelope-from mmacy@FreeBSD.org) Message-Id: <201902232056.x1NKufKt075476@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mmacy set sender to mmacy@FreeBSD.org using -f From: Matt Macy Date: Sat, 23 Feb 2019 20:56:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r344485 - in head/sys/compat: lindebugfs linuxkpi/common/include/linux linuxkpi/common/src X-SVN-Group: head X-SVN-Commit-Author: mmacy X-SVN-Commit-Paths: in head/sys/compat: lindebugfs linuxkpi/common/include/linux linuxkpi/common/src X-SVN-Commit-Revision: 344485 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 1DFA96F31F X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.96 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.97)[-0.966,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 23 Feb 2019 20:56:42 -0000 Author: mmacy Date: Sat Feb 23 20:56:41 2019 New Revision: 344485 URL: https://svnweb.freebsd.org/changeset/base/344485 Log: import linux debugfs support Reviewed by: hps@ MFC after: 1 week Sponsored by: iX Systems Differential Revision: https://reviews.freebsd.org/D19258 Added: head/sys/compat/lindebugfs/ head/sys/compat/lindebugfs/lindebugfs.c (contents, props changed) head/sys/compat/linuxkpi/common/include/linux/debugfs.h (contents, props changed) head/sys/compat/linuxkpi/common/include/linux/seq_file.h (contents, props changed) head/sys/compat/linuxkpi/common/src/linux_seq_file.c (contents, props changed) Added: head/sys/compat/lindebugfs/lindebugfs.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/compat/lindebugfs/lindebugfs.c Sat Feb 23 20:56:41 2019 (r344485) @@ -0,0 +1,309 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2016-2018, Matthew Macy + * + * 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 +#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 +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +MALLOC_DEFINE(M_DFSINT, "debugfsint", "Linux debugfs internal"); + +static struct pfs_node *debugfs_root; + +#define DM_SYMLINK 0x1 +#define DM_DIR 0x2 +#define DM_FILE 0x3 + +struct dentry_meta { + struct dentry dm_dnode; + const struct file_operations *dm_fops; + void *dm_data; + umode_t dm_mode; + int dm_type; +}; + +static int +debugfs_attr(PFS_ATTR_ARGS) +{ + struct dentry_meta *dm; + + dm = pn->pn_data; + + vap->va_mode = dm->dm_mode; + return (0); +} + +static int +debugfs_destroy(PFS_DESTROY_ARGS) +{ + struct dentry_meta *dm; + + dm = pn->pn_data; + if (dm->dm_type == DM_SYMLINK) + free(dm->dm_data, M_DFSINT); + + free(dm, M_DFSINT); + return (0); +} + +static int +debugfs_fill(PFS_FILL_ARGS) +{ + struct dentry_meta *d; + struct linux_file lf; + struct seq_file *sf; + struct vnode vn; + void *buf; + int rc; + size_t len; + off_t off; + + d = pn->pn_data; + + if ((rc = linux_set_current_flags(curthread, M_NOWAIT))) + return (rc); + vn.v_data = d->dm_data; + buf = uio->uio_iov[0].iov_base; + len = min(uio->uio_iov[0].iov_len, uio->uio_resid); + off = 0; + lf.private_data = NULL; + rc = d->dm_fops->open(&vn, &lf); + if (rc < 0) { +#ifdef INVARIANTS + printf("%s:%d open failed with %d\n", __FUNCTION__, __LINE__, rc); +#endif + return (-rc); + } + sf = lf.private_data; + sf->buf = sb; + if (uio->uio_rw == UIO_READ) + rc = d->dm_fops->read(&lf, NULL, len, &off); + else + rc = d->dm_fops->write(&lf, buf, len, &off); + if (d->dm_fops->release) + d->dm_fops->release(&vn, &lf); + else + single_release(&vn, &lf); + + if (rc < 0) { +#ifdef INVARIANTS + printf("%s:%d read/write failed with %d\n", __FUNCTION__, __LINE__, rc); +#endif + return (-rc); + } + return (0); +} + +static int +debugfs_fill_data(PFS_FILL_ARGS) +{ + struct dentry_meta *dm; + + dm = pn->pn_data; + sbuf_printf(sb, "%s", (char *)dm->dm_data); + return (0); +} + +struct dentry * +debugfs_create_file(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops) +{ + struct dentry_meta *dm; + struct dentry *dnode; + struct pfs_node *pnode; + int flags; + + dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO); + if (dm == NULL) + return (NULL); + dnode = &dm->dm_dnode; + dm->dm_fops = fops; + dm->dm_data = data; + dm->dm_mode = mode; + dm->dm_type = DM_FILE; + if (parent != NULL) + pnode = parent->d_pfs_node; + else + pnode = debugfs_root; + + flags = fops->write ? PFS_RDWR : PFS_RD; + dnode->d_pfs_node = pfs_create_file(pnode, name, debugfs_fill, + debugfs_attr, NULL, debugfs_destroy, flags | PFS_NOWAIT); + if (dnode->d_pfs_node == NULL) { + free(dm, M_DFSINT); + return (NULL); + } + dnode->d_pfs_node->pn_data = dm; + + return (dnode); +} + +struct dentry * +debugfs_create_dir(const char *name, struct dentry *parent) +{ + struct dentry_meta *dm; + struct dentry *dnode; + struct pfs_node *pnode; + + dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO); + if (dm == NULL) + return (NULL); + dnode = &dm->dm_dnode; + dm->dm_mode = 0700; + dm->dm_type = DM_DIR; + if (parent != NULL) + pnode = parent->d_pfs_node; + else + pnode = debugfs_root; + + dnode->d_pfs_node = pfs_create_dir(pnode, name, debugfs_attr, NULL, debugfs_destroy, PFS_RD | PFS_NOWAIT); + if (dnode->d_pfs_node == NULL) { + free(dm, M_DFSINT); + return (NULL); + } + dnode->d_pfs_node->pn_data = dm; + return (dnode); +} + +struct dentry * +debugfs_create_symlink(const char *name, struct dentry *parent, + const char *dest) +{ + struct dentry_meta *dm; + struct dentry *dnode; + struct pfs_node *pnode; + void *data; + + data = strdup_flags(dest, M_DFSINT, M_NOWAIT); + if (data == NULL) + return (NULL); + dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO); + if (dm == NULL) + goto fail1; + dnode = &dm->dm_dnode; + dm->dm_mode = 0700; + dm->dm_type = DM_SYMLINK; + dm->dm_data = data; + if (parent != NULL) + pnode = parent->d_pfs_node; + else + pnode = debugfs_root; + + dnode->d_pfs_node = pfs_create_link(pnode, name, &debugfs_fill_data, NULL, NULL, NULL, PFS_NOWAIT); + if (dnode->d_pfs_node == NULL) + goto fail; + dnode->d_pfs_node->pn_data = dm; + return (dnode); + fail: + free(dm, M_DFSINT); + fail1: + free(data, M_DFSINT); + return (NULL); +} + +void +debugfs_remove(struct dentry *dnode) +{ + if (dnode == NULL) + return; + + pfs_destroy(dnode->d_pfs_node); +} + +void +debugfs_remove_recursive(struct dentry *dnode) +{ + if (dnode == NULL) + return; + + pfs_destroy(dnode->d_pfs_node); +} + + +static int +debugfs_init(PFS_INIT_ARGS) +{ + + debugfs_root = pi->pi_root; + return (0); +} + +static int +debugfs_uninit(PFS_INIT_ARGS) +{ + return (0); +} + +#ifdef PR_ALLOW_MOUNT_LINSYSFS +PSEUDOFS(debugfs, 1, PR_ALLOW_MOUNT_LINSYSFS); +#else +PSEUDOFS(debugfs, 1, VFCF_JAIL); +#endif Added: head/sys/compat/linuxkpi/common/include/linux/debugfs.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/compat/linuxkpi/common/include/linux/debugfs.h Sat Feb 23 20:56:41 2019 (r344485) @@ -0,0 +1,51 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2016-2018, Matthew Macy + * + * 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +#ifndef _LINUX_DEBUGFS_H_ +#define _LINUX_DEBUGFS_H_ + +#include +#include + +#include + +void debugfs_remove(struct dentry *dentry); + +struct dentry *debugfs_create_file(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops); + +struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); + +struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, + const char *dest); + +void debugfs_remove_recursive(struct dentry *dentry); + +#endif Added: head/sys/compat/linuxkpi/common/include/linux/seq_file.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/compat/linuxkpi/common/include/linux/seq_file.h Sat Feb 23 20:56:41 2019 (r344485) @@ -0,0 +1,71 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2016-2018, Matthew Macy + * + * 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +#ifndef _LINUX_SEQ_FILE_H_ +#define _LINUX_SEQ_FILE_H_ + +#include + +struct seq_operations; +struct linux_file; + +#define inode vnode + +struct seq_file { + struct sbuf *buf; + + const struct seq_operations *op; + const struct linux_file *file; + void *private; +}; + +struct seq_operations { + void * (*start) (struct seq_file *m, off_t *pos); + void (*stop) (struct seq_file *m, void *v); + void * (*next) (struct seq_file *m, void *v, off_t *pos); + int (*show) (struct seq_file *m, void *v); +}; + +ssize_t seq_read(struct linux_file *, char *, size_t, off_t *); +int seq_write(struct seq_file *seq, const void *data, size_t len); + +int seq_open(struct linux_file *f, const struct seq_operations *op); +int seq_release(struct inode *inode, struct linux_file *file); + +off_t seq_lseek(struct linux_file *file, off_t offset, int whence); +int single_open(struct linux_file *, int (*)(struct seq_file *, void *), void *); +int single_release(struct inode *, struct linux_file *); + +#define seq_printf(m, fmt, ...) sbuf_printf((m)->buf, (fmt), ##__VA_ARGS__) + +#define seq_puts(m, str) sbuf_printf((m)->buf, str) +#define seq_putc(m, str) sbuf_putc((m)->buf, str) + + +#endif /* _LINUX_SEQ_FILE_H_ */ Added: head/sys/compat/linuxkpi/common/src/linux_seq_file.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/compat/linuxkpi/common/src/linux_seq_file.c Sat Feb 23 20:56:41 2019 (r344485) @@ -0,0 +1,157 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2016-2018, Matthew Macy + * + * 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 +#include +#include +#include +#include +#include + +#include +#include + +#undef file +MALLOC_DEFINE(M_LSEQ, "seq_file", "seq_file"); + +ssize_t +seq_read(struct linux_file *f, char *ubuf, size_t size, off_t *ppos) +{ + struct seq_file *m = f->private_data; + void *p; + int rc; + off_t pos = 0; + + p = m->op->start(m, &pos); + rc = m->op->show(m, p); + if (rc) + return (rc); + return (size); +} + +int +seq_write(struct seq_file *seq, const void *data, size_t len) +{ + + return (sbuf_bcpy(seq->buf, data, len)); +} + +/* + * This only needs to be a valid address for lkpi + * drivers it should never actually be called + */ +off_t +seq_lseek(struct linux_file *file, off_t offset, int whence) +{ + + panic("%s not supported\n", __FUNCTION__); + return (0); +} + +static void * +single_start(struct seq_file *p, off_t *pos) +{ + + return ((void *)(uintptr_t)(*pos == 0)); +} + +static void * +single_next(struct seq_file *p, void *v, off_t *pos) +{ + + ++*pos; + return (NULL); +} + +static void +single_stop(struct seq_file *p, void *v) +{ +} + +int +seq_open(struct linux_file *f, const struct seq_operations *op) +{ + struct seq_file *p; + + if (f->private_data != NULL) + log(LOG_WARNING, "%s private_data not NULL", __func__); + + if ((p = malloc(sizeof(*p), M_LSEQ, M_NOWAIT|M_ZERO)) == NULL) + return (-ENOMEM); + + f->private_data = p; + p->op = op; + p->file = f; + return (0); +} + +int +single_open(struct linux_file *f, int (*show)(struct seq_file *, void *), void *d) +{ + struct seq_operations *op; + int rc = -ENOMEM; + + op = malloc(sizeof(*op), M_LSEQ, M_NOWAIT); + if (op) { + op->start = single_start; + op->next = single_next; + op->stop = single_stop; + op->show = show; + rc = seq_open(f, op); + if (rc) + free(op, M_LSEQ); + else + ((struct seq_file *)f->private_data)->private = d; + + } + return (rc); +} + +int +seq_release(struct inode *inode __unused, struct linux_file *file) +{ + struct seq_file *m; + + m = file->private_data; + free(m, M_LSEQ); + return (0); +} + +int +single_release(struct vnode *v, struct linux_file *f) +{ + const struct seq_operations *op = ((struct seq_file *)f->private_data)->op; + int rc; + + rc = seq_release(v, f); + free(__DECONST(void *, op), M_LSEQ); + return (rc); +}