The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/lindebugfs/lindebugfs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2016-2018, Matthew Macy <mmacy@freebsd.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/queue.h>
   35 #include <sys/blist.h>
   36 #include <sys/conf.h>
   37 #include <sys/exec.h>
   38 #include <sys/filedesc.h>
   39 #include <sys/kernel.h>
   40 #include <sys/linker.h>
   41 #include <sys/malloc.h>
   42 #include <sys/mount.h>
   43 #include <sys/mutex.h>
   44 #include <sys/proc.h>
   45 #include <sys/resourcevar.h>
   46 #include <sys/sbuf.h>
   47 #include <sys/smp.h>
   48 #include <sys/socket.h>
   49 #include <sys/vnode.h>
   50 #include <sys/bus.h>
   51 #include <sys/pciio.h>
   52 
   53 #include <dev/pci/pcivar.h>
   54 #include <dev/pci/pcireg.h>
   55 
   56 #include <net/if.h>
   57 
   58 #include <vm/vm.h>
   59 #include <vm/pmap.h>
   60 #include <vm/vm_map.h>
   61 #include <vm/vm_param.h>
   62 #include <vm/vm_object.h>
   63 #include <vm/swap_pager.h>
   64 
   65 #include <machine/bus.h>
   66 
   67 #include <compat/linux/linux_ioctl.h>
   68 #include <compat/linux/linux_mib.h>
   69 #include <compat/linux/linux_util.h>
   70 #include <fs/pseudofs/pseudofs.h>
   71 
   72 #include <asm/atomic.h>
   73 #include <linux/compat.h>
   74 #include <linux/debugfs.h>
   75 #include <linux/fs.h>
   76 
   77 MALLOC_DEFINE(M_DFSINT, "debugfsint", "Linux debugfs internal");
   78 
   79 static struct pfs_node *debugfs_root;
   80 
   81 #define DM_SYMLINK 0x1
   82 #define DM_DIR 0x2
   83 #define DM_FILE 0x3
   84 
   85 struct dentry_meta {
   86         struct dentry dm_dnode;
   87         const struct file_operations *dm_fops;
   88         void *dm_data;
   89         umode_t dm_mode;
   90         int dm_type;
   91 };
   92 
   93 static int
   94 debugfs_attr(PFS_ATTR_ARGS)
   95 {
   96         struct dentry_meta *dm;
   97 
   98         dm = pn->pn_data;
   99 
  100         vap->va_mode = dm->dm_mode;
  101         return (0);
  102 }
  103 
  104 static int
  105 debugfs_destroy(PFS_DESTROY_ARGS)
  106 {
  107         struct dentry_meta *dm;
  108 
  109         dm = pn->pn_data;
  110         if (dm->dm_type == DM_SYMLINK)
  111                 free(dm->dm_data, M_DFSINT);
  112 
  113         free(dm, M_DFSINT);
  114         return (0);
  115 }
  116 
  117 static int
  118 debugfs_fill(PFS_FILL_ARGS)
  119 {
  120         struct dentry_meta *d;
  121         struct linux_file lf = {};
  122         struct vnode vn;
  123         char *buf;
  124         int rc;
  125         off_t off = 0;
  126 
  127         if ((rc = linux_set_current_flags(curthread, M_NOWAIT)))
  128                 return (rc);
  129 
  130         d = pn->pn_data;
  131         vn.v_data = d->dm_data;
  132 
  133         rc = d->dm_fops->open(&vn, &lf);
  134         if (rc < 0) {
  135 #ifdef INVARIANTS
  136                 printf("%s:%d open failed with %d\n", __FUNCTION__, __LINE__, rc);
  137 #endif
  138                 return (-rc);
  139         }
  140 
  141         rc = -ENODEV;
  142         if (uio->uio_rw == UIO_READ && d->dm_fops->read) {
  143                 rc = -ENOMEM;
  144                 buf = (char *) malloc(sb->s_size, M_DFSINT, M_ZERO | M_NOWAIT);
  145                 if (buf != NULL) {
  146                         rc = d->dm_fops->read(&lf, buf, sb->s_size, &off);
  147                         if (rc > 0)
  148                                 sbuf_bcpy(sb, buf, strlen(buf));
  149 
  150                         free(buf, M_DFSINT);
  151                 }
  152         } else if (uio->uio_rw == UIO_WRITE && d->dm_fops->write) {
  153                 sbuf_finish(sb);
  154                 rc = d->dm_fops->write(&lf, sbuf_data(sb), sbuf_len(sb), &off);
  155         }
  156 
  157         if (d->dm_fops->release)
  158                 d->dm_fops->release(&vn, &lf);
  159         else
  160                 single_release(&vn, &lf);
  161 
  162         if (rc < 0) {
  163 #ifdef INVARIANTS
  164                 printf("%s:%d read/write failed with %d\n", __FUNCTION__, __LINE__, rc);
  165 #endif
  166                 return (-rc);
  167         }
  168         return (0);
  169 }
  170 
  171 static int
  172 debugfs_fill_data(PFS_FILL_ARGS)
  173 {
  174         struct dentry_meta *dm;
  175 
  176         dm = pn->pn_data;
  177         sbuf_printf(sb, "%s", (char *)dm->dm_data);
  178         return (0);
  179 }
  180 
  181 struct dentry *
  182 debugfs_create_file(const char *name, umode_t mode,
  183     struct dentry *parent, void *data,
  184     const struct file_operations *fops)
  185 {
  186         struct dentry_meta *dm;
  187         struct dentry *dnode;
  188         struct pfs_node *pnode;
  189         int flags;
  190 
  191         dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
  192         if (dm == NULL)
  193                 return (NULL);
  194         dnode = &dm->dm_dnode;
  195         dm->dm_fops = fops;
  196         dm->dm_data = data;
  197         dm->dm_mode = mode;
  198         dm->dm_type = DM_FILE;
  199         if (parent != NULL)
  200                 pnode = parent->d_pfs_node;
  201         else
  202                 pnode = debugfs_root;
  203 
  204         flags = fops->write ? PFS_RDWR : PFS_RD;
  205         dnode->d_pfs_node = pfs_create_file(pnode, name, debugfs_fill,
  206             debugfs_attr, NULL, debugfs_destroy, flags | PFS_NOWAIT);
  207         if (dnode->d_pfs_node == NULL) {
  208                 free(dm, M_DFSINT);
  209                 return (NULL);
  210         }
  211         dnode->d_pfs_node->pn_data = dm;
  212 
  213         return (dnode);
  214 }
  215 
  216 struct dentry *
  217 debugfs_create_file_size(const char *name, umode_t mode,
  218     struct dentry *parent, void *data,
  219     const struct file_operations *fops,
  220     loff_t file_size __unused)
  221 {
  222 
  223         return debugfs_create_file(name, mode, parent, data, fops);
  224 }
  225 
  226 /*
  227  * NOTE: Files created with the _unsafe moniker will not be protected from
  228  * debugfs core file removals. It is the responsibility of @fops to protect
  229  * its file using debugfs_file_get() and debugfs_file_put().
  230  *
  231  * FreeBSD's LinuxKPI lindebugfs does not perform file removals at the time
  232  * of writing. Therefore there is no difference between functions with _unsafe
  233  * and functions without _unsafe when using lindebugfs. Functions with _unsafe
  234  * exist only for Linux compatibility.
  235  */
  236 struct dentry *
  237 debugfs_create_file_unsafe(const char *name, umode_t mode,
  238     struct dentry *parent, void *data,
  239     const struct file_operations *fops)
  240 {
  241 
  242         return (debugfs_create_file(name, mode, parent, data, fops));
  243 }
  244 
  245 struct dentry *
  246 debugfs_create_mode_unsafe(const char *name, umode_t mode,
  247     struct dentry *parent, void *data,
  248     const struct file_operations *fops,
  249     const struct file_operations *fops_ro,
  250     const struct file_operations *fops_wo)
  251 {
  252         umode_t read = mode & S_IRUGO;
  253         umode_t write = mode & S_IWUGO;
  254 
  255         if (read && !write)
  256                 return (debugfs_create_file_unsafe(name, mode, parent, data, fops_ro));
  257 
  258         if (write && !read)
  259                 return (debugfs_create_file_unsafe(name, mode, parent, data, fops_wo));
  260 
  261         return (debugfs_create_file_unsafe(name, mode, parent, data, fops));
  262 }
  263 
  264 struct dentry *
  265 debugfs_create_dir(const char *name, struct dentry *parent)
  266 {
  267         struct dentry_meta *dm;
  268         struct dentry *dnode;
  269         struct pfs_node *pnode;
  270 
  271         dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
  272         if (dm == NULL)
  273                 return (NULL);
  274         dnode = &dm->dm_dnode;
  275         dm->dm_mode = 0700;
  276         dm->dm_type = DM_DIR;
  277         if (parent != NULL)
  278                 pnode = parent->d_pfs_node;
  279         else
  280                 pnode = debugfs_root;
  281 
  282         dnode->d_pfs_node = pfs_create_dir(pnode, name, debugfs_attr, NULL, debugfs_destroy, PFS_RD | PFS_NOWAIT);
  283         if (dnode->d_pfs_node == NULL) {
  284                 free(dm, M_DFSINT);
  285                 return (NULL);
  286         }
  287         dnode->d_pfs_node->pn_data = dm;
  288         return (dnode);
  289 }
  290 
  291 struct dentry *
  292 debugfs_create_symlink(const char *name, struct dentry *parent,
  293     const char *dest)
  294 {
  295         struct dentry_meta *dm;
  296         struct dentry *dnode;
  297         struct pfs_node *pnode;
  298         void *data;
  299 
  300         data = strdup_flags(dest, M_DFSINT, M_NOWAIT);
  301         if (data == NULL)
  302                 return (NULL);
  303         dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
  304         if (dm == NULL)
  305                 goto fail1;
  306         dnode = &dm->dm_dnode;
  307         dm->dm_mode = 0700;
  308         dm->dm_type = DM_SYMLINK;
  309         dm->dm_data = data;
  310         if (parent != NULL)
  311                 pnode = parent->d_pfs_node;
  312         else
  313                 pnode = debugfs_root;
  314 
  315         dnode->d_pfs_node = pfs_create_link(pnode, name, &debugfs_fill_data, NULL, NULL, NULL, PFS_NOWAIT);
  316         if (dnode->d_pfs_node == NULL)
  317                 goto fail;
  318         dnode->d_pfs_node->pn_data = dm;
  319         return (dnode);
  320  fail:
  321         free(dm, M_DFSINT);
  322  fail1:
  323         free(data, M_DFSINT);
  324         return (NULL);
  325 }
  326 
  327 void
  328 debugfs_remove(struct dentry *dnode)
  329 {
  330         if (dnode == NULL)
  331                 return;
  332 
  333         pfs_destroy(dnode->d_pfs_node);
  334 }
  335 
  336 void
  337 debugfs_remove_recursive(struct dentry *dnode)
  338 {
  339         if (dnode == NULL)
  340                 return;
  341 
  342         pfs_destroy(dnode->d_pfs_node);
  343 }
  344 
  345 static int
  346 debugfs_bool_get(void *data, uint64_t *ullval)
  347 {
  348         bool *bval = data;
  349 
  350         if (*bval)
  351                 *ullval = 1;
  352         else
  353                 *ullval = 0;
  354 
  355         return (0);
  356 }
  357 
  358 static int
  359 debugfs_bool_set(void *data, uint64_t ullval)
  360 {
  361         bool *bval = data;
  362 
  363         if (ullval)
  364                 *bval = 1;
  365         else
  366                 *bval = 0;
  367 
  368         return (0);
  369 }
  370 
  371 DEFINE_DEBUGFS_ATTRIBUTE(fops_bool, debugfs_bool_get, debugfs_bool_set, "%llu\n");
  372 DEFINE_DEBUGFS_ATTRIBUTE(fops_bool_ro, debugfs_bool_get, NULL, "%llu\n");
  373 DEFINE_DEBUGFS_ATTRIBUTE(fops_bool_wo, NULL, debugfs_bool_set, "%llu\n");
  374 
  375 void
  376 debugfs_create_bool(const char *name, umode_t mode, struct dentry *parent, bool *value)
  377 {
  378 
  379         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_bool,
  380             &fops_bool_ro, &fops_bool_wo);
  381 }
  382 
  383 
  384 static int
  385 debugfs_u8_get(void *data, uint64_t *value)
  386 {
  387         uint8_t *u8data = data;
  388         *value = *u8data;
  389         return (0);
  390 }
  391 
  392 static int
  393 debugfs_u8_set(void *data, uint64_t value)
  394 {
  395         uint8_t *u8data = data;
  396         *u8data = (uint8_t)value;
  397         return (0);
  398 }
  399 
  400 DEFINE_DEBUGFS_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%u\n");
  401 DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%u\n");
  402 DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%u\n");
  403 
  404 void
  405 debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent, uint8_t *value)
  406 {
  407 
  408         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u8,
  409             &fops_u8_ro, &fops_u8_wo);
  410 }
  411 
  412 DEFINE_DEBUGFS_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%016llx\n");
  413 DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%016llx\n");
  414 DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%016llx\n");
  415 
  416 void
  417 debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, uint8_t *value)
  418 {
  419 
  420         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x8,
  421             &fops_x8_ro, &fops_x8_wo);
  422 }
  423 
  424 
  425 static int
  426 debugfs_u16_get(void *data, uint64_t *value)
  427 {
  428         uint16_t *u16data = data;
  429         *value = *u16data;
  430         return (0);
  431 }
  432 
  433 static int
  434 debugfs_u16_set(void *data, uint64_t value)
  435 {
  436         uint16_t *u16data = data;
  437         *u16data = (uint16_t)value;
  438         return (0);
  439 }
  440 
  441 DEFINE_DEBUGFS_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%u\n");
  442 DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%u\n");
  443 DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%u\n");
  444 
  445 void
  446 debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, uint16_t *value)
  447 {
  448 
  449         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u16,
  450             &fops_u16_ro, &fops_u16_wo);
  451 }
  452 
  453 DEFINE_DEBUGFS_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%016llx\n");
  454 DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%016llx\n");
  455 DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%016llx\n");
  456 
  457 void
  458 debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, uint16_t *value)
  459 {
  460 
  461         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x16,
  462             &fops_x16_ro, &fops_x16_wo);
  463 }
  464 
  465 
  466 static int
  467 debugfs_u32_get(void *data, uint64_t *value)
  468 {
  469         uint32_t *u32data = data;
  470         *value = *u32data;
  471         return (0);
  472 }
  473 
  474 static int
  475 debugfs_u32_set(void *data, uint64_t value)
  476 {
  477         uint32_t *u32data = data;
  478         *u32data = (uint32_t)value;
  479         return (0);
  480 }
  481 
  482 DEFINE_DEBUGFS_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%u\n");
  483 DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%u\n");
  484 DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%u\n");
  485 
  486 void
  487 debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, uint32_t *value)
  488 {
  489 
  490         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32,
  491             &fops_u32_ro, &fops_u32_wo);
  492 }
  493 
  494 DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%016llx\n");
  495 DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%016llx\n");
  496 DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%016llx\n");
  497 
  498 void
  499 debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, uint32_t *value)
  500 {
  501 
  502         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x32,
  503             &fops_x32_ro, &fops_x32_wo);
  504 }
  505 
  506 
  507 static int
  508 debugfs_u64_get(void *data, uint64_t *value)
  509 {
  510         uint64_t *u64data = data;
  511         *value = *u64data;
  512         return (0);
  513 }
  514 
  515 static int
  516 debugfs_u64_set(void *data, uint64_t value)
  517 {
  518         uint64_t *u64data = data;
  519         *u64data = (uint64_t)value;
  520         return (0);
  521 }
  522 
  523 DEFINE_DEBUGFS_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%u\n");
  524 DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%u\n");
  525 DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%u\n");
  526 
  527 void
  528 debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, uint64_t *value)
  529 {
  530 
  531         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u64,
  532             &fops_u64_ro, &fops_u64_wo);
  533 }
  534 
  535 DEFINE_DEBUGFS_ATTRIBUTE(fops_x64, debugfs_u64_get, debugfs_u64_set, "0x%016llx\n");
  536 DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_ro, debugfs_u64_get, NULL, "0x%016llx\n");
  537 DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n");
  538 
  539 void
  540 debugfs_create_x64(const char *name, umode_t mode, struct dentry *parent, uint64_t *value)
  541 {
  542 
  543         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x64,
  544             &fops_x64_ro, &fops_x64_wo);
  545 }
  546 
  547 
  548 static int
  549 debugfs_ulong_get(void *data, uint64_t *value)
  550 {
  551         uint64_t *uldata = data;
  552         *value = *uldata;
  553         return (0);
  554 }
  555 
  556 static int
  557 debugfs_ulong_set(void *data, uint64_t value)
  558 {
  559         uint64_t *uldata = data;
  560         *uldata = value;
  561         return (0);
  562 }
  563 
  564 DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong, debugfs_ulong_get, debugfs_ulong_set, "%llu\n");
  565 DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_ro, debugfs_ulong_get, NULL, "%llu\n");
  566 DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n");
  567 
  568 void
  569 debugfs_create_ulong(const char *name, umode_t mode, struct dentry *parent, unsigned long *value)
  570 {
  571 
  572         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_ulong,
  573             &fops_ulong_ro, &fops_ulong_wo);
  574 }
  575 
  576 
  577 static int
  578 debugfs_atomic_t_get(void *data, uint64_t *value)
  579 {
  580         atomic_t *atomic_data = data;
  581         *value = atomic_read(atomic_data);
  582         return (0);
  583 }
  584 
  585 static int
  586 debugfs_atomic_t_set(void *data, uint64_t value)
  587 {
  588         atomic_t *atomic_data = data;
  589         atomic_set(atomic_data, (int)value);
  590         return (0);
  591 }
  592 
  593 DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, debugfs_atomic_t_set, "%d\n");
  594 DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, "%d\n");
  595 DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, "%d\n");
  596 
  597 void
  598 debugfs_create_atomic_t(const char *name, umode_t mode, struct dentry *parent, atomic_t *value)
  599 {
  600 
  601         debugfs_create_mode_unsafe(name, mode, parent, value, &fops_atomic_t,
  602             &fops_atomic_t_ro, &fops_atomic_t_wo);
  603 }
  604 
  605 
  606 static ssize_t
  607 fops_blob_read(struct file *filp, char __user *ubuf, size_t read_size, loff_t *ppos)
  608 {
  609         struct debugfs_blob_wrapper *blob;
  610 
  611         blob = filp->private_data;
  612         if (blob == NULL)
  613                 return (-EINVAL);
  614         if (blob->size == 0 || blob->data == NULL)
  615                 return (-EINVAL);
  616 
  617         return (simple_read_from_buffer(ubuf, read_size, ppos, blob->data, blob->size));
  618 }
  619 
  620 static int
  621 fops_blob_open(struct inode *inode, struct file *filp)
  622 {
  623 
  624         return (simple_open(inode, filp));
  625 }
  626 
  627 static const struct file_operations __fops_blob_ro = {
  628         .owner = THIS_MODULE,
  629         .open = fops_blob_open,
  630         .read = fops_blob_read,
  631         .llseek = no_llseek
  632 };
  633 
  634 struct dentry *
  635 debugfs_create_blob(const char *name, umode_t mode, struct dentry *parent,
  636     struct debugfs_blob_wrapper *value)
  637 {
  638         /* Blobs are read-only. */
  639         return (debugfs_create_file(name, mode & 0444, parent, value, &__fops_blob_ro));
  640 }
  641 
  642 
  643 static int
  644 lindebugfs_init(PFS_INIT_ARGS)
  645 {
  646 
  647         debugfs_root = pi->pi_root;
  648 
  649         (void)debugfs_create_symlink("kcov", NULL, "/dev/kcov");
  650 
  651         return (0);
  652 }
  653 
  654 static int
  655 lindebugfs_uninit(PFS_INIT_ARGS)
  656 {
  657 
  658         return (0);
  659 }
  660 
  661 PSEUDOFS(lindebugfs, 1, VFCF_JAIL);
  662 MODULE_DEPEND(lindebugfs, linuxkpi, 1, 1, 1);

Cache object: 03ee23eed64b888bc3c10e7cdc937e66


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.