/*
       * fs/sysfs/group.c - Operations for adding/removing multiple files at once.
       *
       * Copyright (c) 2003 Patrick Mochel
       * Copyright (c) 2003 Open Source Development Lab
       * Copyright (c) 2013 Greg Kroah-Hartman
       * Copyright (c) 2013 The Linux Foundation
       *
       * This file is released undert the GPL v2.
       *
       */
      
      #include <linux/kobject.h>
      #include <linux/module.h>
      #include <linux/dcache.h>
      #include <linux/namei.h>
      #include <linux/err.h>
      #include "sysfs.h"
      
      
      static void remove_files(struct kernfs_node *parent,
                               const struct attribute_group *grp)
      {
              struct attribute *const *attr;
              struct bin_attribute *const *bin_attr;
      
  481         if (grp->attrs)
  481                 for (attr = grp->attrs; *attr; attr++)
  479                         kernfs_remove_by_name(parent, (*attr)->name);
  480         if (grp->bin_attrs)
    9                 for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
    9                         kernfs_remove_by_name(parent, (*bin_attr)->attr.name);
  480 }
      
      static int create_files(struct kernfs_node *parent, struct kobject *kobj,
                              const struct attribute_group *grp, int update)
      {
              struct attribute *const *attr;
              struct bin_attribute *const *bin_attr;
              int error = 0, i;
      
              if (grp->attrs) {
  651                 for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
  651                         umode_t mode = (*attr)->mode;
      
                              /*
                               * In update mode, we're changing the permissions or
                               * visibility.  Do this by first removing then
                               * re-adding (if required) the file.
                               */
                              if (update)
                                      kernfs_remove_by_name(parent, (*attr)->name);
  651                         if (grp->is_visible) {
                                      mode = grp->is_visible(kobj, *attr, i);
                                      if (!mode)
                                              continue;
                              }
      
  651                         WARN(mode & ~(SYSFS_PREALLOC | 0664),
                                   "Attribute %s: Invalid permissions 0%o\n",
                                   (*attr)->name, mode);
      
  651                         mode &= SYSFS_PREALLOC | 0664;
                              error = sysfs_add_file_mode_ns(parent, *attr, false,
                                                             mode, NULL);
                              if (unlikely(error))
                                      break;
                      }
                      if (error) {
                              remove_files(parent, grp);
                              goto exit;
                      }
              }
      
  649         if (grp->bin_attrs) {
                      for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) {
                              umode_t mode = (*bin_attr)->attr.mode;
      
                              if (update)
                                      kernfs_remove_by_name(parent,
                                                      (*bin_attr)->attr.name);
                              if (grp->is_bin_visible) {
                                      mode = grp->is_bin_visible(kobj, *bin_attr, i);
                                      if (!mode)
                                              continue;
                              }
      
                              WARN(mode & ~(SYSFS_PREALLOC | 0664),
                                   "Attribute %s: Invalid permissions 0%o\n",
                                   (*bin_attr)->attr.name, mode);
      
                              mode &= SYSFS_PREALLOC | 0664;
                              error = sysfs_add_file_mode_ns(parent,
                                              &(*bin_attr)->attr, true,
                                              mode, NULL);
                              if (error)
                                      break;
                      }
                      if (error)
                              remove_files(parent, grp);
              }
      exit:
              return error;
      }
      
      
      static int internal_create_group(struct kobject *kobj, int update,
                                       const struct attribute_group *grp)
      {
              struct kernfs_node *kn;
              int error;
      
  651         BUG_ON(!kobj || (!update && !kobj->sd));
      
              /* Updates may happen before the object has been instantiated */
              if (unlikely(update && !kobj->sd))
                      return -EINVAL;
  651         if (!grp->attrs && !grp->bin_attrs) {
                      WARN(1, "sysfs: (bin_)attrs not set by subsystem for group: %s/%s\n",
                              kobj->name, grp->name ?: "");
                      return -EINVAL;
              }
  651         if (grp->name) {
  650                 kn = kernfs_create_dir(kobj->sd, grp->name,
                                             S_IRWXU | S_IRUGO | S_IXUGO, kobj);
                      if (IS_ERR(kn)) {
                              if (PTR_ERR(kn) == -EEXIST)
                                      sysfs_warn_dup(kobj->sd, grp->name);
                              return PTR_ERR(kn);
                      }
              } else
                      kn = kobj->sd;
  651         kernfs_get(kn);
  651         error = create_files(kn, kobj, grp, update);
              if (error) {
                      if (grp->name)
                              kernfs_remove(kn);
              }
  649         kernfs_put(kn);
  649         return error;
      }
      
      /**
       * sysfs_create_group - given a directory kobject, create an attribute group
       * @kobj:        The kobject to create the group on
       * @grp:        The attribute group to create
       *
       * This function creates a group for the first time.  It will explicitly
       * warn and error if any of the attribute files being created already exist.
       *
       * Returns 0 on success or error code on failure.
       */
      int sysfs_create_group(struct kobject *kobj,
                             const struct attribute_group *grp)
      {
  651         return internal_create_group(kobj, 0, grp);
      }
      EXPORT_SYMBOL_GPL(sysfs_create_group);
      
      /**
       * sysfs_create_groups - given a directory kobject, create a bunch of attribute groups
       * @kobj:        The kobject to create the group on
       * @groups:        The attribute groups to create, NULL terminated
       *
       * This function creates a bunch of attribute groups.  If an error occurs when
       * creating a group, all previously created groups will be removed, unwinding
       * everything back to the original state when this function was called.
       * It will explicitly warn and error if any of the attribute files being
       * created already exist.
       *
       * Returns 0 on success or error code from sysfs_create_group on failure.
       */
  588 int sysfs_create_groups(struct kobject *kobj,
                              const struct attribute_group **groups)
      {
              int error = 0;
              int i;
      
  588         if (!groups)
  587                 return 0;
      
  588         for (i = 0; groups[i]; i++) {
  588                 error = sysfs_create_group(kobj, groups[i]);
                      if (error) {
                              while (--i >= 0)
                                      sysfs_remove_group(kobj, groups[i]);
                              break;
                      }
              }
              return error;
      }
      EXPORT_SYMBOL_GPL(sysfs_create_groups);
      
      /**
       * sysfs_update_group - given a directory kobject, update an attribute group
       * @kobj:        The kobject to update the group on
       * @grp:        The attribute group to update
       *
       * This function updates an attribute group.  Unlike
       * sysfs_create_group(), it will explicitly not warn or error if any
       * of the attribute files being created already exist.  Furthermore,
       * if the visibility of the files has changed through the is_visible()
       * callback, it will update the permissions and add or remove the
       * relevant files.
       *
       * The primary use for this function is to call it after making a change
       * that affects group visibility.
       *
       * Returns 0 on success or error code on failure.
       */
      int sysfs_update_group(struct kobject *kobj,
                             const struct attribute_group *grp)
      {
              return internal_create_group(kobj, 1, grp);
      }
      EXPORT_SYMBOL_GPL(sysfs_update_group);
      
      /**
       * sysfs_remove_group: remove a group from a kobject
       * @kobj:        kobject to remove the group from
       * @grp:        group to remove
       *
       * This function removes a group of attributes from a kobject.  The attributes
       * previously have to have been created for this group, otherwise it will fail.
       */
      void sysfs_remove_group(struct kobject *kobj,
                              const struct attribute_group *grp)
      {
  481         struct kernfs_node *parent = kobj->sd;
              struct kernfs_node *kn;
      
              if (grp->name) {
  481                 kn = kernfs_find_and_get(parent, grp->name);
                      if (!kn) {
                              WARN(!kn, KERN_WARNING
                                   "sysfs group '%s' not found for kobject '%s'\n",
                                   grp->name, kobject_name(kobj));
                              return;
                      }
              } else {
                      kn = parent;
  223                 kernfs_get(kn);
              }
      
  481         remove_files(kn, grp);
              if (grp->name)
  480                 kernfs_remove(kn);
      
  480         kernfs_put(kn);
      }
      EXPORT_SYMBOL_GPL(sysfs_remove_group);
      
      /**
       * sysfs_remove_groups - remove a list of groups
       *
       * @kobj:        The kobject for the groups to be removed from
       * @groups:        NULL terminated list of groups to be removed
       *
       * If groups is not NULL, remove the specified groups from the kobject.
       */
  224 void sysfs_remove_groups(struct kobject *kobj,
                               const struct attribute_group **groups)
      {
              int i;
      
  224         if (!groups)
                      return;
  224         for (i = 0; groups[i]; i++)
  223                 sysfs_remove_group(kobj, groups[i]);
      }
      EXPORT_SYMBOL_GPL(sysfs_remove_groups);
      
      /**
       * sysfs_merge_group - merge files into a pre-existing attribute group.
       * @kobj:        The kobject containing the group.
       * @grp:        The files to create and the attribute group they belong to.
       *
       * This function returns an error if the group doesn't exist or any of the
       * files already exist in that group, in which case none of the new files
       * are created.
       */
      int sysfs_merge_group(struct kobject *kobj,
                             const struct attribute_group *grp)
      {
              struct kernfs_node *parent;
              int error = 0;
              struct attribute *const *attr;
              int i;
      
  580         parent = kernfs_find_and_get(kobj->sd, grp->name);
              if (!parent)
                      return -ENOENT;
      
  579         for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr))
  579                 error = sysfs_add_file(parent, *attr, false);
  577         if (error) {
                      while (--i >= 0)
                              kernfs_remove_by_name(parent, (*--attr)->name);
              }
  577         kernfs_put(parent);
      
  577         return error;
      }
      EXPORT_SYMBOL_GPL(sysfs_merge_group);
      
      /**
       * sysfs_unmerge_group - remove files from a pre-existing attribute group.
       * @kobj:        The kobject containing the group.
       * @grp:        The files to remove and the attribute group they belong to.
       */
      void sysfs_unmerge_group(struct kobject *kobj,
                             const struct attribute_group *grp)
      {
              struct kernfs_node *parent;
              struct attribute *const *attr;
      
  230         parent = kernfs_find_and_get(kobj->sd, grp->name);
              if (parent) {
  230                 for (attr = grp->attrs; *attr; ++attr)
  230                         kernfs_remove_by_name(parent, (*attr)->name);
  229                 kernfs_put(parent);
              }
  229 }
      EXPORT_SYMBOL_GPL(sysfs_unmerge_group);
      
      /**
       * sysfs_add_link_to_group - add a symlink to an attribute group.
       * @kobj:        The kobject containing the group.
       * @group_name:        The name of the group.
       * @target:        The target kobject of the symlink to create.
       * @link_name:        The name of the symlink to create.
       */
      int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name,
                                  struct kobject *target, const char *link_name)
      {
              struct kernfs_node *parent;
              int error = 0;
      
              parent = kernfs_find_and_get(kobj->sd, group_name);
              if (!parent)
                      return -ENOENT;
      
              error = sysfs_create_link_sd(parent, target, link_name);
              kernfs_put(parent);
      
              return error;
      }
      EXPORT_SYMBOL_GPL(sysfs_add_link_to_group);
      
      /**
       * sysfs_remove_link_from_group - remove a symlink from an attribute group.
       * @kobj:        The kobject containing the group.
       * @group_name:        The name of the group.
       * @link_name:        The name of the symlink to remove.
       */
      void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
                                        const char *link_name)
      {
              struct kernfs_node *parent;
      
              parent = kernfs_find_and_get(kobj->sd, group_name);
              if (parent) {
                      kernfs_remove_by_name(parent, link_name);
                      kernfs_put(parent);
              }
      }
      EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group);
      
      /**
       * __compat_only_sysfs_link_entry_to_kobj - add a symlink to a kobject pointing
       * to a group or an attribute
       * @kobj:                The kobject containing the group.
       * @target_kobj:        The target kobject.
       * @target_name:        The name of the target group or attribute.
       */
      int __compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj,
                                            struct kobject *target_kobj,
                                            const char *target_name)
      {
              struct kernfs_node *target;
              struct kernfs_node *entry;
              struct kernfs_node *link;
      
              /*
               * We don't own @target_kobj and it may be removed at any time.
               * Synchronize using sysfs_symlink_target_lock. See sysfs_remove_dir()
               * for details.
               */
              spin_lock(&sysfs_symlink_target_lock);
              target = target_kobj->sd;
              if (target)
                      kernfs_get(target);
              spin_unlock(&sysfs_symlink_target_lock);
              if (!target)
                      return -ENOENT;
      
              entry = kernfs_find_and_get(target_kobj->sd, target_name);
              if (!entry) {
                      kernfs_put(target);
                      return -ENOENT;
              }
      
              link = kernfs_create_link(kobj->sd, target_name, entry);
              if (IS_ERR(link) && PTR_ERR(link) == -EEXIST)
                      sysfs_warn_dup(kobj->sd, target_name);
      
              kernfs_put(entry);
              kernfs_put(target);
              return IS_ERR(link) ? PTR_ERR(link) : 0;
      }
      EXPORT_SYMBOL_GPL(__compat_only_sysfs_link_entry_to_kobj);
      /*
       * Cryptographic API.
       *
       * Deflate algorithm (RFC 1951), implemented here primarily for use
       * by IPCOMP (RFC 3173 & RFC 2394).
       *
       * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
       *
       * This program is free software; you can redistribute it and/or modify it
       * under the terms of the GNU General Public License as published by the Free
       * Software Foundation; either version 2 of the License, or (at your option)
       * any later version.
       *
       * FIXME: deflate transforms will require up to a total of about 436k of kernel
       * memory on i386 (390k for compression, the rest for decompression), as the
       * current zlib kernel code uses a worst case pre-allocation system by default.
       * This needs to be fixed so that the amount of memory required is properly
       * related to the  winbits and memlevel parameters.
       *
       * The default winbits of 11 should suit most packets, and it may be something
       * to configure on a per-tfm basis in the future.
       *
       * Currently, compression history is not maintained between tfm calls, as
       * it is not needed for IPCOMP and keeps the code simpler.  It can be
       * implemented if someone wants it.
       */
      #include <linux/init.h>
      #include <linux/module.h>
      #include <linux/crypto.h>
      #include <linux/zlib.h>
      #include <linux/vmalloc.h>
      #include <linux/interrupt.h>
      #include <linux/mm.h>
      #include <linux/net.h>
      
      #define DEFLATE_DEF_LEVEL                Z_DEFAULT_COMPRESSION
      #define DEFLATE_DEF_WINBITS                11
      #define DEFLATE_DEF_MEMLEVEL                MAX_MEM_LEVEL
      
      struct deflate_ctx {
              struct z_stream_s comp_stream;
              struct z_stream_s decomp_stream;
      };
      
      static int deflate_comp_init(struct deflate_ctx *ctx)
      {
              int ret = 0;
              struct z_stream_s *stream = &ctx->comp_stream;
      
              stream->workspace = vzalloc(zlib_deflate_workspacesize(
                                      -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL));
              if (!stream->workspace) {
                      ret = -ENOMEM;
                      goto out;
              }
   12         ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
                                      -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
                                      Z_DEFAULT_STRATEGY);
              if (ret != Z_OK) {
                      ret = -EINVAL;
                      goto out_free;
              }
      out:
              return ret;
      out_free:
              vfree(stream->workspace);
              goto out;
      }
      
      static int deflate_decomp_init(struct deflate_ctx *ctx)
      {
              int ret = 0;
   12         struct z_stream_s *stream = &ctx->decomp_stream;
      
   12         stream->workspace = vzalloc(zlib_inflate_workspacesize());
              if (!stream->workspace) {
                      ret = -ENOMEM;
                      goto out;
              }
              ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
              if (ret != Z_OK) {
                      ret = -EINVAL;
                      goto out_free;
              }
      out:
              return ret;
      out_free:
              vfree(stream->workspace);
              goto out;
      }
      
      static void deflate_comp_exit(struct deflate_ctx *ctx)
      {
              zlib_deflateEnd(&ctx->comp_stream);
              vfree(ctx->comp_stream.workspace);
      }
      
      static void deflate_decomp_exit(struct deflate_ctx *ctx)
      {
              zlib_inflateEnd(&ctx->decomp_stream);
              vfree(ctx->decomp_stream.workspace);
      }
      
      static int deflate_init(struct crypto_tfm *tfm)
      {
   12         struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
              int ret;
      
   12         ret = deflate_comp_init(ctx);
              if (ret)
                      goto out;
   12         ret = deflate_decomp_init(ctx);
              if (ret)
                      deflate_comp_exit(ctx);
      out:
   12         return ret;
      }
      
      static void deflate_exit(struct crypto_tfm *tfm)
      {
              struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
      
              deflate_comp_exit(ctx);
              deflate_decomp_exit(ctx);
      }
      
      static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
                                  unsigned int slen, u8 *dst, unsigned int *dlen)
      {
              int ret = 0;
              struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
              struct z_stream_s *stream = &dctx->comp_stream;
      
              ret = zlib_deflateReset(stream);
              if (ret != Z_OK) {
                      ret = -EINVAL;
                      goto out;
              }
      
              stream->next_in = (u8 *)src;
              stream->avail_in = slen;
              stream->next_out = (u8 *)dst;
              stream->avail_out = *dlen;
      
              ret = zlib_deflate(stream, Z_FINISH);
              if (ret != Z_STREAM_END) {
                      ret = -EINVAL;
                      goto out;
              }
              ret = 0;
              *dlen = stream->total_out;
      out:
              return ret;
      }
      
      static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
                                    unsigned int slen, u8 *dst, unsigned int *dlen)
      {
      
              int ret = 0;
              struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
              struct z_stream_s *stream = &dctx->decomp_stream;
      
              ret = zlib_inflateReset(stream);
              if (ret != Z_OK) {
                      ret = -EINVAL;
                      goto out;
              }
      
              stream->next_in = (u8 *)src;
              stream->avail_in = slen;
              stream->next_out = (u8 *)dst;
              stream->avail_out = *dlen;
      
              ret = zlib_inflate(stream, Z_SYNC_FLUSH);
              /*
               * Work around a bug in zlib, which sometimes wants to taste an extra
               * byte when being used in the (undocumented) raw deflate mode.
               * (From USAGI).
               */
              if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
                      u8 zerostuff = 0;
                      stream->next_in = &zerostuff;
                      stream->avail_in = 1;
                      ret = zlib_inflate(stream, Z_FINISH);
              }
              if (ret != Z_STREAM_END) {
                      ret = -EINVAL;
                      goto out;
              }
              ret = 0;
              *dlen = stream->total_out;
      out:
              return ret;
      }
      
      static struct crypto_alg alg = {
              .cra_name                = "deflate",
              .cra_flags                = CRYPTO_ALG_TYPE_COMPRESS,
              .cra_ctxsize                = sizeof(struct deflate_ctx),
              .cra_module                = THIS_MODULE,
              .cra_init                = deflate_init,
              .cra_exit                = deflate_exit,
              .cra_u                        = { .compress = {
              .coa_compress                 = deflate_compress,
              .coa_decompress          = deflate_decompress } }
      };
      
      static int __init deflate_mod_init(void)
      {
              return crypto_register_alg(&alg);
      }
      
      static void __exit deflate_mod_fini(void)
      {
              crypto_unregister_alg(&alg);
      }
      
      module_init(deflate_mod_init);
      module_exit(deflate_mod_fini);
      
      MODULE_LICENSE("GPL");
      MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
      MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
      MODULE_ALIAS_CRYPTO("deflate");
      /*
       *  linux/fs/binfmt_script.c
       *
       *  Copyright (C) 1996  Martin von Löwis
       *  original #!-checking implemented by tytso.
       */
      
      #include <linux/module.h>
      #include <linux/string.h>
      #include <linux/stat.h>
      #include <linux/binfmts.h>
      #include <linux/init.h>
      #include <linux/file.h>
      #include <linux/err.h>
      #include <linux/fs.h>
      
   14 static inline bool spacetab(char c) { return c == ' ' || c == '\t'; }
      static inline char *next_non_spacetab(char *first, const char *last)
      {
   13         for (; first <= last; first++)
   14                 if (!spacetab(*first))
                              return first;
              return NULL;
      }
      static inline char *next_terminator(char *first, const char *last)
      {
   14         for (; first <= last; first++)
   14                 if (spacetab(*first) || !*first)
                              return first;
              return NULL;
      }
      
      static int load_script(struct linux_binprm *bprm)
      {
              const char *i_arg, *i_name;
              char *cp, *buf_end;
              struct file *file;
              char interp[BINPRM_BUF_SIZE];
              int retval;
      
              /* Not ours to exec if we don't start with "#!". */
  105         if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
                      return -ENOEXEC;
      
              /*
               * If the script filename will be inaccessible after exec, typically
               * because it is a "/dev/fd/<fd>/.." path against an O_CLOEXEC fd, give
               * up now (on the assumption that the interpreter will want to load
               * this file).
               */
   41         if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
                      return -ENOENT;
      
              /* Release since we are not mapping a binary into memory. */
   40         allow_write_access(bprm->file);
   40         fput(bprm->file);
              bprm->file = NULL;
      
              /*
               * This section handles parsing the #! line into separate
               * interpreter path and argument strings. We must be careful
               * because bprm->buf is not yet guaranteed to be NUL-terminated
               * (though the buffer will have trailing NUL padding when the
               * file size was smaller than the buffer size).
               *
               * We do not want to exec a truncated interpreter path, so either
               * we find a newline (which indicates nothing is truncated), or
               * we find a space/tab/NUL after the interpreter path (which
               * itself may be preceded by spaces/tabs). Truncating the
               * arguments is fine: the interpreter can re-read the script to
               * parse them on its own.
               */
   14         buf_end = bprm->buf + sizeof(bprm->buf) - 1;
              cp = strnchr(bprm->buf, sizeof(bprm->buf), '\n');
              if (!cp) {
   14                 cp = next_non_spacetab(bprm->buf + 2, buf_end);
   14                 if (!cp)
                              return -ENOEXEC; /* Entire buf is spaces/tabs */
                      /*
                       * If there is no later space/tab/NUL we must assume the
                       * interpreter path is truncated.
                       */
   14                 if (!next_terminator(cp, buf_end))
                              return -ENOEXEC;
                      cp = buf_end;
              }
              /* NUL-terminate the buffer and any trailing spaces/tabs. */
   38         *cp = '\0';
              while (cp > bprm->buf) {
   38                 cp--;
   38                 if ((*cp == ' ') || (*cp == '\t'))
    2                         *cp = '\0';
                      else
                              break;
              }
   38         for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
   38         if (*cp == '\0') 
                      return -ENOEXEC; /* No interpreter name found */
   37         i_name = cp;
              i_arg = NULL;
   37         for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
                      /* nothing */ ;
   19         while ((*cp == ' ') || (*cp == '\t'))
   19                 *cp++ = '\0';
   19         if (*cp)
   16                 i_arg = cp;
   37         strcpy (interp, i_name);
              /*
               * OK, we've parsed out the interpreter name and
               * (optional) argument.
               * Splice in (1) the interpreter's name for argv[0]
               *           (2) (optional) argument to interpreter
               *           (3) filename of shell script (replace argv[0])
               *
               * This is done in reverse order, because of how the
               * user environment and arguments are stored.
               */
              retval = remove_arg_zero(bprm);
   99         if (retval)
                      return retval;
   38         retval = copy_strings_kernel(1, &bprm->interp, bprm);
              if (retval < 0) return retval; 
   38         bprm->argc++;
              if (i_arg) {
   16                 retval = copy_strings_kernel(1, &i_arg, bprm);
                      if (retval < 0) return retval; 
   16                 bprm->argc++;
              }
   38         retval = copy_strings_kernel(1, &i_name, bprm);
              if (retval) return retval; 
   38         bprm->argc++;
              retval = bprm_change_interp(interp, bprm);
              if (retval < 0)
                      return retval;
      
              /*
               * OK, now restart the process with the interpreter's dentry.
               */
   38         file = open_exec(interp);
              if (IS_ERR(file))
    3                 return PTR_ERR(file);
      
   29         bprm->file = file;
              retval = prepare_binprm(bprm);
              if (retval < 0)
                      return retval;
   28         return search_binary_handler(bprm);
      }
      
      static struct linux_binfmt script_format = {
              .module                = THIS_MODULE,
              .load_binary        = load_script,
      };
      
      static int __init init_script_binfmt(void)
      {
              register_binfmt(&script_format);
              return 0;
      }
      
      static void __exit exit_script_binfmt(void)
      {
              unregister_binfmt(&script_format);
      }
      
      core_initcall(init_script_binfmt);
      module_exit(exit_script_binfmt);
      MODULE_LICENSE("GPL");
      /*
       *  linux/kernel/compat.c
       *
       *  Kernel compatibililty routines for e.g. 32 bit syscall support
       *  on 64 bit kernels.
       *
       *  Copyright (C) 2002-2003 Stephen Rothwell, IBM Corporation
       *
       *  This program is free software; you can redistribute it and/or modify
       *  it under the terms of the GNU General Public License version 2 as
       *  published by the Free Software Foundation.
       */
      
      #include <linux/linkage.h>
      #include <linux/compat.h>
      #include <linux/errno.h>
      #include <linux/time.h>
      #include <linux/signal.h>
      #include <linux/sched.h>        /* for MAX_SCHEDULE_TIMEOUT */
      #include <linux/syscalls.h>
      #include <linux/unistd.h>
      #include <linux/security.h>
      #include <linux/timex.h>
      #include <linux/export.h>
      #include <linux/migrate.h>
      #include <linux/posix-timers.h>
      #include <linux/times.h>
      #include <linux/ptrace.h>
      #include <linux/gfp.h>
      
      #include <asm/uaccess.h>
      
      static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
      {
    9         memset(txc, 0, sizeof(struct timex));
      
    9         if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) ||
    9                         __get_user(txc->modes, &utp->modes) ||
    6                         __get_user(txc->offset, &utp->offset) ||
    6                         __get_user(txc->freq, &utp->freq) ||
    6                         __get_user(txc->maxerror, &utp->maxerror) ||
    6                         __get_user(txc->esterror, &utp->esterror) ||
    6                         __get_user(txc->status, &utp->status) ||
    6                         __get_user(txc->constant, &utp->constant) ||
    6                         __get_user(txc->precision, &utp->precision) ||
    6                         __get_user(txc->tolerance, &utp->tolerance) ||
    6                         __get_user(txc->time.tv_sec, &utp->time.tv_sec) ||
    6                         __get_user(txc->time.tv_usec, &utp->time.tv_usec) ||
    6                         __get_user(txc->tick, &utp->tick) ||
    6                         __get_user(txc->ppsfreq, &utp->ppsfreq) ||
    6                         __get_user(txc->jitter, &utp->jitter) ||
    6                         __get_user(txc->shift, &utp->shift) ||
    6                         __get_user(txc->stabil, &utp->stabil) ||
    6                         __get_user(txc->jitcnt, &utp->jitcnt) ||
    6                         __get_user(txc->calcnt, &utp->calcnt) ||
    6                         __get_user(txc->errcnt, &utp->errcnt) ||
    6                         __get_user(txc->stbcnt, &utp->stbcnt))
    9                 return -EFAULT;
      
              return 0;
      }
      
      static int compat_put_timex(struct compat_timex __user *utp, struct timex *txc)
      {
    5         if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||
    5                         __put_user(txc->modes, &utp->modes) ||
    5                         __put_user(txc->offset, &utp->offset) ||
    5                         __put_user(txc->freq, &utp->freq) ||
    5                         __put_user(txc->maxerror, &utp->maxerror) ||
    5                         __put_user(txc->esterror, &utp->esterror) ||
    5                         __put_user(txc->status, &utp->status) ||
    5                         __put_user(txc->constant, &utp->constant) ||
    5                         __put_user(txc->precision, &utp->precision) ||
    5                         __put_user(txc->tolerance, &utp->tolerance) ||
    5                         __put_user(txc->time.tv_sec, &utp->time.tv_sec) ||
    4                         __put_user(txc->time.tv_usec, &utp->time.tv_usec) ||
    4                         __put_user(txc->tick, &utp->tick) ||
    4                         __put_user(txc->ppsfreq, &utp->ppsfreq) ||
    4                         __put_user(txc->jitter, &utp->jitter) ||
    4                         __put_user(txc->shift, &utp->shift) ||
    4                         __put_user(txc->stabil, &utp->stabil) ||
    4                         __put_user(txc->jitcnt, &utp->jitcnt) ||
    4                         __put_user(txc->calcnt, &utp->calcnt) ||
    4                         __put_user(txc->errcnt, &utp->errcnt) ||
    4                         __put_user(txc->stbcnt, &utp->stbcnt) ||
    4                         __put_user(txc->tai, &utp->tai))
    4                 return -EFAULT;
              return 0;
      }
      
    5 COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv,
                             struct timezone __user *, tz)
      {
    5         if (tv) {
                      struct timeval ktv;
    3                 do_gettimeofday(&ktv);
    1                 if (compat_put_timeval(&ktv, tv))
    2                         return -EFAULT;
              }
    3         if (tz) {
    2                 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
                              return -EFAULT;
              }
      
              return 0;
      }
      
    7 COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv,
                             struct timezone __user *, tz)
      {
              struct timeval user_tv;
              struct timespec        new_ts;
              struct timezone new_tz;
      
    7         if (tv) {
                      if (compat_get_timeval(&user_tv, tv))
                              return -EFAULT;
    1                 new_ts.tv_sec = user_tv.tv_sec;
                      new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
              }
    4         if (tz) {
    3                 if (copy_from_user(&new_tz, tz, sizeof(*tz)))
                              return -EFAULT;
              }
      
    3         return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
      }
      
      static int __compat_get_timeval(struct timeval *tv, const struct compat_timeval __user *ctv)
      {
    3         return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) ||
    3                         __get_user(tv->tv_sec, &ctv->tv_sec) ||
    3                         __get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
      }
      
      static int __compat_put_timeval(const struct timeval *tv, struct compat_timeval __user *ctv)
      {
    3         return (!access_ok(VERIFY_WRITE, ctv, sizeof(*ctv)) ||
    3                         __put_user(tv->tv_sec, &ctv->tv_sec) ||
    3                         __put_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
      }
      
      static int __compat_get_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
      {
   21         return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
   21                         __get_user(ts->tv_sec, &cts->tv_sec) ||
   20                         __get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
      }
      
      static int __compat_put_timespec(const struct timespec *ts, struct compat_timespec __user *cts)
      {
    3         return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) ||
    3                         __put_user(ts->tv_sec, &cts->tv_sec) ||
    3                         __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
      }
      
      int compat_get_timeval(struct timeval *tv, const void __user *utv)
      {
              if (COMPAT_USE_64BIT_TIME)
                      return copy_from_user(tv, utv, sizeof(*tv)) ? -EFAULT : 0;
              else
                      return __compat_get_timeval(tv, utv);
      }
      EXPORT_SYMBOL_GPL(compat_get_timeval);
      
      int compat_put_timeval(const struct timeval *tv, void __user *utv)
      {
              if (COMPAT_USE_64BIT_TIME)
                      return copy_to_user(utv, tv, sizeof(*tv)) ? -EFAULT : 0;
              else
                      return __compat_put_timeval(tv, utv);
      }
      EXPORT_SYMBOL_GPL(compat_put_timeval);
      
      int compat_get_timespec(struct timespec *ts, const void __user *uts)
    6 {
              if (COMPAT_USE_64BIT_TIME)
                      return copy_from_user(ts, uts, sizeof(*ts)) ? -EFAULT : 0;
              else
                      return __compat_get_timespec(ts, uts);
      }
      EXPORT_SYMBOL_GPL(compat_get_timespec);
      
      int compat_put_timespec(const struct timespec *ts, void __user *uts)
      {
              if (COMPAT_USE_64BIT_TIME)
                      return copy_to_user(uts, ts, sizeof(*ts)) ? -EFAULT : 0;
              else
                      return __compat_put_timespec(ts, uts);
      }
      EXPORT_SYMBOL_GPL(compat_put_timespec);
      
      int compat_convert_timespec(struct timespec __user **kts,
                                  const void __user *cts)
      {
              struct timespec ts;
              struct timespec __user *uts;
      
              if (!cts || COMPAT_USE_64BIT_TIME) {
                      *kts = (struct timespec __user *)cts;
                      return 0;
              }
      
              uts = compat_alloc_user_space(sizeof(ts));
              if (!uts)
                      return -EFAULT;
              if (compat_get_timespec(&ts, cts))
                      return -EFAULT;
              if (copy_to_user(uts, &ts, sizeof(ts)))
                      return -EFAULT;
      
              *kts = uts;
              return 0;
      }
      
      static long compat_nanosleep_restart(struct restart_block *restart)
      {
              struct compat_timespec __user *rmtp;
              struct timespec rmt;
              mm_segment_t oldfs;
              long ret;
      
              restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
              oldfs = get_fs();
              set_fs(KERNEL_DS);
              ret = hrtimer_nanosleep_restart(restart);
              set_fs(oldfs);
      
              if (ret == -ERESTART_RESTARTBLOCK) {
                      rmtp = restart->nanosleep.compat_rmtp;
      
                      if (rmtp && compat_put_timespec(&rmt, rmtp))
                              return -EFAULT;
              }
      
              return ret;
      }
      
    3 COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
                             struct compat_timespec __user *, rmtp)
      {
              struct timespec tu, rmt;
              mm_segment_t oldfs;
              long ret;
      
              if (compat_get_timespec(&tu, rqtp))
                      return -EFAULT;
      
              if (!timespec_valid(&tu))
    3                 return -EINVAL;
      
              oldfs = get_fs();
              set_fs(KERNEL_DS);
              ret = hrtimer_nanosleep(&tu,
                                      rmtp ? (struct timespec __user *)&rmt : NULL,
                                      HRTIMER_MODE_REL, CLOCK_MONOTONIC);
              set_fs(oldfs);
      
              /*
               * hrtimer_nanosleep() can only return 0 or
               * -ERESTART_RESTARTBLOCK here because:
               *
               * - we call it with HRTIMER_MODE_REL and therefor exclude the
               *   -ERESTARTNOHAND return path.
               *
               * - we supply the rmtp argument from the task stack (due to
               *   the necessary compat conversion. So the update cannot
               *   fail, which excludes the -EFAULT return path as well. If
               *   it fails nevertheless we have a bigger problem and wont
               *   reach this place anymore.
               *
               * - if the return value is 0, we do not have to update rmtp
               *    because there is no remaining time.
               *
               * We check for -ERESTART_RESTARTBLOCK nevertheless if the
               * core implementation decides to return random nonsense.
               */
              if (ret == -ERESTART_RESTARTBLOCK) {
                      struct restart_block *restart = &current->restart_block;
      
                      restart->fn = compat_nanosleep_restart;
                      restart->nanosleep.compat_rmtp = rmtp;
      
                      if (rmtp && compat_put_timespec(&rmt, rmtp))
                              return -EFAULT;
              }
              return ret;
      }
      
      static inline long get_compat_itimerval(struct itimerval *o,
                      struct compat_itimerval __user *i)
      {
    1         return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
                      (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
                       __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
                       __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
                       __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
      }
      
      static inline long put_compat_itimerval(struct compat_itimerval __user *o,
                      struct itimerval *i)
      {
    1         return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
                      (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
                       __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
                       __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
                       __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
      }
      
    1 COMPAT_SYSCALL_DEFINE2(getitimer, int, which,
                      struct compat_itimerval __user *, it)
      {
              struct itimerval kit;
              int error;
      
              error = do_getitimer(which, &kit);
    1         if (!error && put_compat_itimerval(it, &kit))
                      error = -EFAULT;
    1         return error;
      }
      
    3 COMPAT_SYSCALL_DEFINE3(setitimer, int, which,
                      struct compat_itimerval __user *, in,
                      struct compat_itimerval __user *, out)
      {
              struct itimerval kin, kout;
              int error;
      
    3         if (in) {
    1                 if (get_compat_itimerval(&kin, in))
                              return -EFAULT;
              } else
    2                 memset(&kin, 0, sizeof(kin));
      
    3         error = do_setitimer(which, &kin, out ? &kout : NULL);
              if (error || !out)
    3                 return error;
              if (put_compat_itimerval(out, &kout))
                      return -EFAULT;
    3         return 0;
      }
      
      static compat_clock_t clock_t_to_compat_clock_t(clock_t x)
      {
              return compat_jiffies_to_clock_t(clock_t_to_jiffies(x));
      }
      
    7 COMPAT_SYSCALL_DEFINE1(times, struct compat_tms __user *, tbuf)
      {
    7         if (tbuf) {
                      struct tms tms;
                      struct compat_tms tmp;
      
    4                 do_sys_times(&tms);
                      /* Convert our struct tms to the compat version. */
                      tmp.tms_utime = clock_t_to_compat_clock_t(tms.tms_utime);
                      tmp.tms_stime = clock_t_to_compat_clock_t(tms.tms_stime);
                      tmp.tms_cutime = clock_t_to_compat_clock_t(tms.tms_cutime);
                      tmp.tms_cstime = clock_t_to_compat_clock_t(tms.tms_cstime);
    2                 if (copy_to_user(tbuf, &tmp, sizeof(tmp)))
    2                         return -EFAULT;
              }
              force_successful_syscall_return();
    5         return compat_jiffies_to_clock_t(jiffies);
      }
      
      #ifdef __ARCH_WANT_SYS_SIGPENDING
      
      /*
       * Assumption: old_sigset_t and compat_old_sigset_t are both
       * types that can be passed to put_user()/get_user().
       */
      
    1 COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set)
      {
              old_sigset_t s;
              long ret;
    1         mm_segment_t old_fs = get_fs();
      
              set_fs(KERNEL_DS);
              ret = sys_sigpending((old_sigset_t __user *) &s);
              set_fs(old_fs);
              if (ret == 0)
    1                 ret = put_user(s, set);
    1         return ret;
      }
      
      #endif
      
      #ifdef __ARCH_WANT_SYS_SIGPROCMASK
      
      /*
       * sys_sigprocmask SIG_SETMASK sets the first (compat) word of the
       * blocked set of signals to the supplied signal set
       */
      static inline void compat_sig_setmask(sigset_t *blocked, compat_sigset_word set)
      {
              memcpy(blocked->sig, &set, sizeof(set));
      }
      
    5 COMPAT_SYSCALL_DEFINE3(sigprocmask, int, how,
                             compat_old_sigset_t __user *, nset,
                             compat_old_sigset_t __user *, oset)
      {
              old_sigset_t old_set, new_set;
              sigset_t new_blocked;
      
    5         old_set = current->blocked.sig[0];
      
              if (nset) {
    3                 if (get_user(new_set, nset))
                              return -EFAULT;
    3                 new_set &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP));
      
                      new_blocked = current->blocked;
      
                      switch (how) {
                      case SIG_BLOCK:
    1                         sigaddsetmask(&new_blocked, new_set);
                              break;
                      case SIG_UNBLOCK:
                              sigdelsetmask(&new_blocked, new_set);
                              break;
                      case SIG_SETMASK:
                              compat_sig_setmask(&new_blocked, new_set);
                              break;
                      default:
                              return -EINVAL;
                      }
      
    1                 set_current_blocked(&new_blocked);
              }
      
    3         if (oset) {
    2                 if (put_user(old_set, oset))
                              return -EFAULT;
              }
      
    5         return 0;
      }
      
      #endif
      
    1 COMPAT_SYSCALL_DEFINE2(setrlimit, unsigned int, resource,
                             struct compat_rlimit __user *, rlim)
      {
              struct rlimit r;
      
    1         if (!access_ok(VERIFY_READ, rlim, sizeof(*rlim)) ||
    1             __get_user(r.rlim_cur, &rlim->rlim_cur) ||
                  __get_user(r.rlim_max, &rlim->rlim_max))
                      return -EFAULT;
      
              if (r.rlim_cur == COMPAT_RLIM_INFINITY)
                      r.rlim_cur = RLIM_INFINITY;
              if (r.rlim_max == COMPAT_RLIM_INFINITY)
                      r.rlim_max = RLIM_INFINITY;
    1         return do_prlimit(current, resource, &r, NULL);
      }
      
      #ifdef COMPAT_RLIM_OLD_INFINITY
      
    4 COMPAT_SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
                             struct compat_rlimit __user *, rlim)
      {
              struct rlimit r;
              int ret;
              mm_segment_t old_fs = get_fs();
      
              set_fs(KERNEL_DS);
              ret = sys_old_getrlimit(resource, (struct rlimit __user *)&r);
              set_fs(old_fs);
      
              if (!ret) {
    3                 if (r.rlim_cur > COMPAT_RLIM_OLD_INFINITY)
                              r.rlim_cur = COMPAT_RLIM_INFINITY;
    3                 if (r.rlim_max > COMPAT_RLIM_OLD_INFINITY)
                              r.rlim_max = COMPAT_RLIM_INFINITY;
      
    3                 if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) ||
                          __put_user(r.rlim_cur, &rlim->rlim_cur) ||
    1                     __put_user(r.rlim_max, &rlim->rlim_max))
                              return -EFAULT;
              }
    4         return ret;
      }
      
      #endif
      
    2 COMPAT_SYSCALL_DEFINE2(getrlimit, unsigned int, resource,
                             struct compat_rlimit __user *, rlim)
      {
              struct rlimit r;
              int ret;
      
              ret = do_prlimit(current, resource, NULL, &r);
              if (!ret) {
    2                 if (r.rlim_cur > COMPAT_RLIM_INFINITY)
    2                         r.rlim_cur = COMPAT_RLIM_INFINITY;
    2                 if (r.rlim_max > COMPAT_RLIM_INFINITY)
    2                         r.rlim_max = COMPAT_RLIM_INFINITY;
      
    2                 if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) ||
                          __put_user(r.rlim_cur, &rlim->rlim_cur) ||
    1                     __put_user(r.rlim_max, &rlim->rlim_max))
                              return -EFAULT;
              }
    2         return ret;
      }
      
      int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
      {
    2         if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) ||
    2             __put_user(r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) ||
    1             __put_user(r->ru_utime.tv_usec, &ru->ru_utime.tv_usec) ||
    1             __put_user(r->ru_stime.tv_sec, &ru->ru_stime.tv_sec) ||
    1             __put_user(r->ru_stime.tv_usec, &ru->ru_stime.tv_usec) ||
    1             __put_user(r->ru_maxrss, &ru->ru_maxrss) ||
    1             __put_user(r->ru_ixrss, &ru->ru_ixrss) ||
    1             __put_user(r->ru_idrss, &ru->ru_idrss) ||
    1             __put_user(r->ru_isrss, &ru->ru_isrss) ||
    1             __put_user(r->ru_minflt, &ru->ru_minflt) ||
    1             __put_user(r->ru_majflt, &ru->ru_majflt) ||
    1             __put_user(r->ru_nswap, &ru->ru_nswap) ||
    1             __put_user(r->ru_inblock, &ru->ru_inblock) ||
    1             __put_user(r->ru_oublock, &ru->ru_oublock) ||
    1             __put_user(r->ru_msgsnd, &ru->ru_msgsnd) ||
    1             __put_user(r->ru_msgrcv, &ru->ru_msgrcv) ||
    1             __put_user(r->ru_nsignals, &ru->ru_nsignals) ||
    1             __put_user(r->ru_nvcsw, &ru->ru_nvcsw) ||
    1             __put_user(r->ru_nivcsw, &ru->ru_nivcsw))
    2                 return -EFAULT;
              return 0;
      }
      
    3 COMPAT_SYSCALL_DEFINE4(wait4,
              compat_pid_t, pid,
              compat_uint_t __user *, stat_addr,
              int, options,
              struct compat_rusage __user *, ru)
      {
              if (!ru) {
    3                 return sys_wait4(pid, stat_addr, options, NULL);
              } else {
                      struct rusage r;
                      int ret;
                      unsigned int status;
                      mm_segment_t old_fs = get_fs();
      
                      set_fs (KERNEL_DS);
                      ret = sys_wait4(pid,
                                      (stat_addr ?
                                       (unsigned int __user *) &status : NULL),
                                      options, (struct rusage __user *) &r);
                      set_fs (old_fs);
      
                      if (ret > 0) {
                              if (put_compat_rusage(&r, ru))
                                      return -EFAULT;
                              if (stat_addr && put_user(status, stat_addr))
                                      return -EFAULT;
                      }
                      return ret;
              }
      }
      
    2 COMPAT_SYSCALL_DEFINE5(waitid,
                      int, which, compat_pid_t, pid,
                      struct compat_siginfo __user *, uinfo, int, options,
                      struct compat_rusage __user *, uru)
      {
              siginfo_t info;
              struct rusage ru;
              long ret;
              mm_segment_t old_fs = get_fs();
      
              memset(&info, 0, sizeof(info));
      
              set_fs(KERNEL_DS);
    2         ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
                               uru ? (struct rusage __user *)&ru : NULL);
              set_fs(old_fs);
      
              if ((ret < 0) || (info.si_signo == 0))
                      return ret;
      
              if (uru) {
                      /* sys_waitid() overwrites everything in ru */
                      if (COMPAT_USE_64BIT_TIME)
                              ret = copy_to_user(uru, &ru, sizeof(ru));
                      else
                              ret = put_compat_rusage(&ru, uru);
                      if (ret)
                              return -EFAULT;
              }
      
              BUG_ON(info.si_code & __SI_MASK);
              info.si_code |= __SI_CHLD;
    2         return copy_siginfo_to_user32(uinfo, &info);
      }
      
      static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
                                          unsigned len, struct cpumask *new_mask)
      {
              unsigned long *k;
      
              if (len < cpumask_size())
    2                 memset(new_mask, 0, cpumask_size());
              else if (len > cpumask_size())
                      len = cpumask_size();
      
              k = cpumask_bits(new_mask);
    3         return compat_get_bitmap(k, user_mask_ptr, len * 8);
      }
      
    3 COMPAT_SYSCALL_DEFINE3(sched_setaffinity, compat_pid_t, pid,
                             unsigned int, len,
                             compat_ulong_t __user *, user_mask_ptr)
      {
              cpumask_var_t new_mask;
              int retval;
      
              if (!alloc_cpumask_var(&new_mask, GFP_KERNEL))
                      return -ENOMEM;
      
    3         retval = compat_get_user_cpu_mask(user_mask_ptr, len, new_mask);
              if (retval)
                      goto out;
      
              retval = sched_setaffinity(pid, new_mask);
      out:
              free_cpumask_var(new_mask);
    3         return retval;
      }
      
    2 COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t,  pid, unsigned int, len,
                             compat_ulong_t __user *, user_mask_ptr)
      {
              int ret;
              cpumask_var_t mask;
      
              if ((len * BITS_PER_BYTE) < nr_cpu_ids)
                      return -EINVAL;
    1         if (len & (sizeof(compat_ulong_t)-1))
                      return -EINVAL;
      
              if (!alloc_cpumask_var(&mask, GFP_KERNEL))
                      return -ENOMEM;
      
    1         ret = sched_getaffinity(pid, mask);
    2         if (ret == 0) {
    1                 size_t retlen = min_t(size_t, len, cpumask_size());
      
                      if (compat_put_bitmap(user_mask_ptr, cpumask_bits(mask), retlen * 8))
                              ret = -EFAULT;
                      else
    1                         ret = retlen;
              }
              free_cpumask_var(mask);
      
              return ret;
      }
      
      int get_compat_itimerspec(struct itimerspec *dst,
                                const struct compat_itimerspec __user *src)
      {
    5         if (__compat_get_timespec(&dst->it_interval, &src->it_interval) ||
    3             __compat_get_timespec(&dst->it_value, &src->it_value))
                      return -EFAULT;
              return 0;
      }
      
      int put_compat_itimerspec(struct compat_itimerspec __user *dst,
                                const struct itimerspec *src)
      {
              if (__compat_put_timespec(&src->it_interval, &dst->it_interval) ||
                  __compat_put_timespec(&src->it_value, &dst->it_value))
                      return -EFAULT;
              return 0;
      }
      
    3 COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
                             struct compat_sigevent __user *, timer_event_spec,
                             timer_t __user *, created_timer_id)
      {
              struct sigevent __user *event = NULL;
      
              if (timer_event_spec) {
                      struct sigevent kevent;
      
    2                 event = compat_alloc_user_space(sizeof(*event));
    1                 if (get_compat_sigevent(&kevent, timer_event_spec) ||
    1                     copy_to_user(event, &kevent, sizeof(*event)))
    1                         return -EFAULT;
              }
      
    2         return sys_timer_create(which_clock, event, created_timer_id);
      }
      
    4 COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
                             struct compat_itimerspec __user *, new,
                             struct compat_itimerspec __user *, old)
      {
              long err;
              mm_segment_t oldfs;
              struct itimerspec newts, oldts;
      
              if (!new)
                      return -EINVAL;
    3         if (get_compat_itimerspec(&newts, new))
                      return -EFAULT;
    2         oldfs = get_fs();
              set_fs(KERNEL_DS);
              err = sys_timer_settime(timer_id, flags,
                                      (struct itimerspec __user *) &newts,
                                      (struct itimerspec __user *) &oldts);
              set_fs(oldfs);
    4         if (!err && old && put_compat_itimerspec(old, &oldts))
                      return -EFAULT;
              return err;
      }
      
    2 COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
                             struct compat_itimerspec __user *, setting)
      {
              long err;
              mm_segment_t oldfs;
              struct itimerspec ts;
      
              oldfs = get_fs();
              set_fs(KERNEL_DS);
              err = sys_timer_gettime(timer_id,
                                      (struct itimerspec __user *) &ts);
              set_fs(oldfs);
    2         if (!err && put_compat_itimerspec(setting, &ts))
                      return -EFAULT;
              return err;
      }
      
    3 COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
                             struct compat_timespec __user *, tp)
      {
              long err;
              mm_segment_t oldfs;
              struct timespec ts;
      
              if (compat_get_timespec(&ts, tp))
                      return -EFAULT;
    1         oldfs = get_fs();
              set_fs(KERNEL_DS);
              err = sys_clock_settime(which_clock,
                                      (struct timespec __user *) &ts);
              set_fs(oldfs);
    3         return err;
      }
      
    4 COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
                             struct compat_timespec __user *, tp)
      {
              long err;
              mm_segment_t oldfs;
              struct timespec ts;
      
              oldfs = get_fs();
              set_fs(KERNEL_DS);
              err = sys_clock_gettime(which_clock,
                                      (struct timespec __user *) &ts);
              set_fs(oldfs);
    4         if (!err && compat_put_timespec(&ts, tp))
                      return -EFAULT;
              return err;
      }
      
    4 COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
                             struct compat_timex __user *, utp)
      {
              struct timex txc;
              mm_segment_t oldfs;
              int err, ret;
      
              err = compat_get_timex(&txc, utp);
              if (err)
    3                 return err;
      
    3         oldfs = get_fs();
              set_fs(KERNEL_DS);
    2         ret = sys_clock_adjtime(which_clock, (struct timex __user *) &txc);
              set_fs(oldfs);
      
              err = compat_put_timex(utp, &txc);
              if (err)
                      return err;
      
              return ret;
      }
      
    1 COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
                             struct compat_timespec __user *, tp)
      {
              long err;
              mm_segment_t oldfs;
              struct timespec ts;
      
              oldfs = get_fs();
              set_fs(KERNEL_DS);
              err = sys_clock_getres(which_clock,
                                     (struct timespec __user *) &ts);
              set_fs(oldfs);
    1         if (!err && tp && compat_put_timespec(&ts, tp))
    1                 return -EFAULT;
              return err;
      }
      
      static long compat_clock_nanosleep_restart(struct restart_block *restart)
      {
              long err;
              mm_segment_t oldfs;
              struct timespec tu;
              struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
      
              restart->nanosleep.rmtp = (struct timespec __user *) &tu;
              oldfs = get_fs();
              set_fs(KERNEL_DS);
              err = clock_nanosleep_restart(restart);
              set_fs(oldfs);
      
              if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
                  compat_put_timespec(&tu, rmtp))
                      return -EFAULT;
      
              if (err == -ERESTART_RESTARTBLOCK) {
                      restart->fn = compat_clock_nanosleep_restart;
                      restart->nanosleep.compat_rmtp = rmtp;
              }
              return err;
      }
      
    4 COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
                             struct compat_timespec __user *, rqtp,
                             struct compat_timespec __user *, rmtp)
      {
              long err;
              mm_segment_t oldfs;
              struct timespec in, out;
              struct restart_block *restart;
      
              if (compat_get_timespec(&in, rqtp))
                      return -EFAULT;
      
    3         oldfs = get_fs();
              set_fs(KERNEL_DS);
              err = sys_clock_nanosleep(which_clock, flags,
                                        (struct timespec __user *) &in,
                                        (struct timespec __user *) &out);
              set_fs(oldfs);
      
    4         if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
                  compat_put_timespec(&out, rmtp))
                      return -EFAULT;
      
              if (err == -ERESTART_RESTARTBLOCK) {
                      restart = &current->restart_block;
                      restart->fn = compat_clock_nanosleep_restart;
                      restart->nanosleep.compat_rmtp = rmtp;
              }
              return err;
      }
      
      /*
       * We currently only need the following fields from the sigevent
       * structure: sigev_value, sigev_signo, sig_notify and (sometimes
       * sigev_notify_thread_id).  The others are handled in user mode.
       * We also assume that copying sigev_value.sival_int is sufficient
       * to keep all the bits of sigev_value.sival_ptr intact.
       */
      int get_compat_sigevent(struct sigevent *event,
                      const struct compat_sigevent __user *u_event)
      {
    2         memset(event, 0, sizeof(*event));
    2         return (!access_ok(VERIFY_READ, u_event, sizeof(*u_event)) ||
    2                 __get_user(event->sigev_value.sival_int,
                              &u_event->sigev_value.sival_int) ||
    1                 __get_user(event->sigev_signo, &u_event->sigev_signo) ||
    1                 __get_user(event->sigev_notify, &u_event->sigev_notify) ||
    1                 __get_user(event->sigev_notify_thread_id,
                              &u_event->sigev_notify_thread_id))
    2                 ? -EFAULT : 0;
      }
      
      long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
                             unsigned long bitmap_size)
      {
              int i, j;
              unsigned long m;
              compat_ulong_t um;
              unsigned long nr_compat_longs;
      
              /* align bitmap up to nearest compat_long_t boundary */
    3         bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
      
    3         if (!access_ok(VERIFY_READ, umask, bitmap_size / 8))
    3                 return -EFAULT;
      
    3         nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
      
              for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
                      m = 0;
      
                      for (j = 0; j < sizeof(m)/sizeof(um); j++) {
                              /*
                               * We dont want to read past the end of the userspace
                               * bitmap. We must however ensure the end of the
                               * kernel bitmap is zeroed.
                               */
    1                         if (nr_compat_longs) {
    1                                 nr_compat_longs--;
                                      if (__get_user(um, umask))
                                              return -EFAULT;
                              } else {
                                      um = 0;
                              }
      
                              umask++;
                              m |= (long)um << (j * BITS_PER_COMPAT_LONG);
                      }
                      *mask++ = m;
              }
      
              return 0;
      }
      
      long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
                             unsigned long bitmap_size)
      {
              int i, j;
              unsigned long m;
              compat_ulong_t um;
              unsigned long nr_compat_longs;
      
              /* align bitmap up to nearest compat_long_t boundary */
    1         bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
      
    1         if (!access_ok(VERIFY_WRITE, umask, bitmap_size / 8))
    1                 return -EFAULT;
      
    1         nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
      
    1         for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
    1                 m = *mask++;
      
                      for (j = 0; j < sizeof(m)/sizeof(um); j++) {
                              um = m;
      
                              /*
                               * We dont want to write past the end of the userspace
                               * bitmap.
                               */
    1                         if (nr_compat_longs) {
    1                                 nr_compat_longs--;
                                      if (__put_user(um, umask))
                                              return -EFAULT;
                              }
      
    1                         umask++;
                              m >>= 4*sizeof(um);
                              m >>= 4*sizeof(um);
                      }
              }
      
              return 0;
      }
      
      void
      sigset_from_compat(sigset_t *set, const compat_sigset_t *compat)
      {
              switch (_NSIG_WORDS) {
              case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 );
              case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 );
              case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 );
              case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 );
              }
      }
      EXPORT_SYMBOL_GPL(sigset_from_compat);
      
      void
      sigset_to_compat(compat_sigset_t *compat, const sigset_t *set)
      {
              switch (_NSIG_WORDS) {
              case 4: compat->sig[7] = (set->sig[3] >> 32); compat->sig[6] = set->sig[3];
              case 3: compat->sig[5] = (set->sig[2] >> 32); compat->sig[4] = set->sig[2];
              case 2: compat->sig[3] = (set->sig[1] >> 32); compat->sig[2] = set->sig[1];
              case 1: compat->sig[1] = (set->sig[0] >> 32); compat->sig[0] = set->sig[0];
              }
      }
      
    3 COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
                      struct compat_siginfo __user *, uinfo,
                      struct compat_timespec __user *, uts, compat_size_t, sigsetsize)
      {
              compat_sigset_t s32;
              sigset_t s;
              struct timespec t;
              siginfo_t info;
              long ret;
      
              if (sigsetsize != sizeof(sigset_t))
                      return -EINVAL;
      
              if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
                      return -EFAULT;
              sigset_from_compat(&s, &s32);
      
              if (uts) {
                      if (compat_get_timespec(&t, uts))
                              return -EFAULT;
              }
      
              ret = do_sigtimedwait(&s, &info, uts ? &t : NULL);
      
              if (ret > 0 && uinfo) {
    3                 if (copy_siginfo_to_user32(uinfo, &info))
                              ret = -EFAULT;
              }
      
              return ret;
      }
      
      #ifdef __ARCH_WANT_COMPAT_SYS_TIME
      
      /* compat_time_t is a 32 bit "long" and needs to get converted. */
      
    2 COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc)
      {
              compat_time_t i;
              struct timeval tv;
      
    2         do_gettimeofday(&tv);
              i = tv.tv_sec;
      
              if (tloc) {
                      if (put_user(i,tloc))
                              return -EFAULT;
              }
              force_successful_syscall_return();
    2         return i;
      }
      
    2 COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
      {
              struct timespec tv;
              int err;
      
              if (get_user(tv.tv_sec, tptr))
                      return -EFAULT;
      
    1         tv.tv_nsec = 0;
      
              err = security_settime(&tv, NULL);
              if (err)
    2                 return err;
      
    1         do_settimeofday(&tv);
              return 0;
      }
      
      #endif /* __ARCH_WANT_COMPAT_SYS_TIME */
      
    5 COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp)
      {
              struct timex txc;
              int err, ret;
      
              err = compat_get_timex(&txc, utp);
              if (err)
                      return err;
      
    3         ret = do_adjtimex(&txc);
      
              err = compat_put_timex(utp, &txc);
              if (err)
                      return err;
      
    4         return ret;
      }
      
      #ifdef CONFIG_NUMA
      COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
                             compat_uptr_t __user *, pages32,
                             const int __user *, nodes,
                             int __user *, status,
                             int, flags)
      {
              const void __user * __user *pages;
              int i;
      
              pages = compat_alloc_user_space(nr_pages * sizeof(void *));
              for (i = 0; i < nr_pages; i++) {
                      compat_uptr_t p;
      
                      if (get_user(p, pages32 + i) ||
                              put_user(compat_ptr(p), pages + i))
                              return -EFAULT;
              }
              return sys_move_pages(pid, nr_pages, pages, nodes, status, flags);
      }
      
      COMPAT_SYSCALL_DEFINE4(migrate_pages, compat_pid_t, pid,
                             compat_ulong_t, maxnode,
                             const compat_ulong_t __user *, old_nodes,
                             const compat_ulong_t __user *, new_nodes)
      {
              unsigned long __user *old = NULL;
              unsigned long __user *new = NULL;
              nodemask_t tmp_mask;
              unsigned long nr_bits;
              unsigned long size;
      
              nr_bits = min_t(unsigned long, maxnode - 1, MAX_NUMNODES);
              size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
              if (old_nodes) {
                      if (compat_get_bitmap(nodes_addr(tmp_mask), old_nodes, nr_bits))
                              return -EFAULT;
                      old = compat_alloc_user_space(new_nodes ? size * 2 : size);
                      if (new_nodes)
                              new = old + size / sizeof(unsigned long);
                      if (copy_to_user(old, nodes_addr(tmp_mask), size))
                              return -EFAULT;
              }
              if (new_nodes) {
                      if (compat_get_bitmap(nodes_addr(tmp_mask), new_nodes, nr_bits))
                              return -EFAULT;
                      if (new == NULL)
                              new = compat_alloc_user_space(size);
                      if (copy_to_user(new, nodes_addr(tmp_mask), size))
                              return -EFAULT;
              }
              return sys_migrate_pages(pid, nr_bits + 1, old, new);
      }
      #endif
      
    1 COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval,
                             compat_pid_t, pid,
                             struct compat_timespec __user *, interval)
      {
              struct timespec t;
              int ret;
              mm_segment_t old_fs = get_fs();
      
              set_fs(KERNEL_DS);
              ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
              set_fs(old_fs);
              if (compat_put_timespec(&t, interval))
                      return -EFAULT;
    1         return ret;
      }
      
      /*
       * Allocate user-space memory for the duration of a single system call,
       * in order to marshall parameters inside a compat thunk.
       */
      void __user *compat_alloc_user_space(unsigned long len)
      {
              void __user *ptr;
      
              /* If len would occupy more than half of the entire compat space... */
    7         if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
                      return NULL;
      
    7         ptr = arch_compat_alloc_user_space(len);
      
    7         if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
                      return NULL;
      
              return ptr;
      }
      EXPORT_SYMBOL_GPL(compat_alloc_user_space);
      /*
       * Functions to sequence FLUSH and FUA writes.
       *
       * Copyright (C) 2011                Max Planck Institute for Gravitational Physics
       * Copyright (C) 2011                Tejun Heo <tj@kernel.org>
       *
       * This file is released under the GPLv2.
       *
       * REQ_{FLUSH|FUA} requests are decomposed to sequences consisted of three
       * optional steps - PREFLUSH, DATA and POSTFLUSH - according to the request
       * properties and hardware capability.
       *
       * If a request doesn't have data, only REQ_PREFLUSH makes sense, which
       * indicates a simple flush request.  If there is data, REQ_PREFLUSH indicates
       * that the device cache should be flushed before the data is executed, and
       * REQ_FUA means that the data must be on non-volatile media on request
       * completion.
       *
       * If the device doesn't have writeback cache, FLUSH and FUA don't make any
       * difference.  The requests are either completed immediately if there's no
       * data or executed as normal requests otherwise.
       *
       * If the device has writeback cache and supports FUA, REQ_PREFLUSH is
       * translated to PREFLUSH but REQ_FUA is passed down directly with DATA.
       *
       * If the device has writeback cache and doesn't support FUA, REQ_PREFLUSH
       * is translated to PREFLUSH and REQ_FUA to POSTFLUSH.
       *
       * The actual execution of flush is double buffered.  Whenever a request
       * needs to execute PRE or POSTFLUSH, it queues at
       * fq->flush_queue[fq->flush_pending_idx].  Once certain criteria are met, a
       * REQ_OP_FLUSH is issued and the pending_idx is toggled.  When the flush
       * completes, all the requests which were pending are proceeded to the next
       * step.  This allows arbitrary merging of different types of FLUSH/FUA
       * requests.
       *
       * Currently, the following conditions are used to determine when to issue
       * flush.
       *
       * C1. At any given time, only one flush shall be in progress.  This makes
       *     double buffering sufficient.
       *
       * C2. Flush is deferred if any request is executing DATA of its sequence.
       *     This avoids issuing separate POSTFLUSHes for requests which shared
       *     PREFLUSH.
       *
       * C3. The second condition is ignored if there is a request which has
       *     waited longer than FLUSH_PENDING_TIMEOUT.  This is to avoid
       *     starvation in the unlikely case where there are continuous stream of
       *     FUA (without FLUSH) requests.
       *
       * For devices which support FUA, it isn't clear whether C2 (and thus C3)
       * is beneficial.
       *
       * Note that a sequenced FLUSH/FUA request with DATA is completed twice.
       * Once while executing DATA and again after the whole sequence is
       * complete.  The first completion updates the contained bio but doesn't
       * finish it so that the bio submitter is notified only after the whole
       * sequence is complete.  This is implemented by testing REQ_FLUSH_SEQ in
       * req_bio_endio().
       *
       * The above peculiarity requires that each FLUSH/FUA request has only one
       * bio attached to it, which is guaranteed as they aren't allowed to be
       * merged in the usual way.
       */
      
      #include <linux/kernel.h>
      #include <linux/module.h>
      #include <linux/bio.h>
      #include <linux/blkdev.h>
      #include <linux/gfp.h>
      #include <linux/blk-mq.h>
      
      #include "blk.h"
      #include "blk-mq.h"
      #include "blk-mq-tag.h"
      
      /* FLUSH/FUA sequences */
      enum {
              REQ_FSEQ_PREFLUSH        = (1 << 0), /* pre-flushing in progress */
              REQ_FSEQ_DATA                = (1 << 1), /* data write in progress */
              REQ_FSEQ_POSTFLUSH        = (1 << 2), /* post-flushing in progress */
              REQ_FSEQ_DONE                = (1 << 3),
      
              REQ_FSEQ_ACTIONS        = REQ_FSEQ_PREFLUSH | REQ_FSEQ_DATA |
                                        REQ_FSEQ_POSTFLUSH,
      
              /*
               * If flush has been pending longer than the following timeout,
               * it's issued even if flush_data requests are still in flight.
               */
              FLUSH_PENDING_TIMEOUT        = 5 * HZ,
      };
      
      static bool blk_kick_flush(struct request_queue *q,
                                 struct blk_flush_queue *fq);
      
      static unsigned int blk_flush_policy(unsigned long fflags, struct request *rq)
      {
              unsigned int policy = 0;
      
              if (blk_rq_sectors(rq))
                      policy |= REQ_FSEQ_DATA;
      
  389         if (fflags & (1UL << QUEUE_FLAG_WC)) {
  389                 if (rq->cmd_flags & REQ_PREFLUSH)
  348                         policy |= REQ_FSEQ_PREFLUSH;
  389                 if (!(fflags & (1UL << QUEUE_FLAG_FUA)) &&
  389                     (rq->cmd_flags & REQ_FUA))
   42                         policy |= REQ_FSEQ_POSTFLUSH;
              }
              return policy;
      }
      
      static unsigned int blk_flush_cur_seq(struct request *rq)
      {
  389         return 1 << ffz(rq->flush.seq);
      }
      
      static void blk_flush_restore_request(struct request *rq)
      {
              /*
               * After flush data completion, @rq->bio is %NULL but we need to
               * complete the bio again.  @rq->biotail is guaranteed to equal the
               * original @rq->bio.  Restore it.
               */
              rq->bio = rq->biotail;
      
              /* make @rq a normal request */
              rq->cmd_flags &= ~REQ_FLUSH_SEQ;
              rq->end_io = rq->flush.saved_end_io;
      }
      
      static bool blk_flush_queue_rq(struct request *rq, bool add_front)
      {
  389         if (rq->q->mq_ops) {
                      struct request_queue *q = rq->q;
      
   34                 blk_mq_add_to_requeue_list(rq, add_front);
                      blk_mq_kick_requeue_list(q);
  388                 return false;
              } else {
  355                 if (add_front)
   30                         list_add(&rq->queuelist, &rq->q->queue_head);
                      else
  325                         list_add_tail(&rq->queuelist, &rq->q->queue_head);
                      return true;
              }
      }
      
      /**
       * blk_flush_complete_seq - complete flush sequence
       * @rq: FLUSH/FUA request being sequenced
       * @fq: flush queue
       * @seq: sequences to complete (mask of %REQ_FSEQ_*, can be zero)
       * @error: whether an error occurred
       *
       * @rq just completed @seq part of its flush sequence, record the
       * completion and trigger the next step.
       *
       * CONTEXT:
       * spin_lock_irq(q->queue_lock or fq->mq_flush_lock)
       *
       * RETURNS:
       * %true if requests were added to the dispatch queue, %false otherwise.
       */
      static bool blk_flush_complete_seq(struct request *rq,
                                         struct blk_flush_queue *fq,
                                         unsigned int seq, int error)
      {
  389         struct request_queue *q = rq->q;
  348         struct list_head *pending = &fq->flush_queue[fq->flush_pending_idx];
              bool queued = false, kicked;
      
              BUG_ON(rq->flush.seq & seq);
  389         rq->flush.seq |= seq;
      
              if (likely(!error))
  389                 seq = blk_flush_cur_seq(rq);
              else
                      seq = REQ_FSEQ_DONE;
      
              switch (seq) {
              case REQ_FSEQ_PREFLUSH:
              case REQ_FSEQ_POSTFLUSH:
                      /* queue for flush */
                      if (list_empty(pending))
  348                         fq->flush_pending_since = jiffies;
  348                 list_move_tail(&rq->flush.list, pending);
                      break;
      
              case REQ_FSEQ_DATA:
   41                 list_move_tail(&rq->flush.list, &fq->flush_data_in_flight);
   41                 queued = blk_flush_queue_rq(rq, true);
                      break;
      
              case REQ_FSEQ_DONE:
                      /*
                       * @rq was previously adjusted by blk_flush_issue() for
                       * flush sequencing and may already have gone through the
                       * flush data request completion path.  Restore @rq for
                       * normal completion and end it.
                       */
                      BUG_ON(!list_empty(&rq->queuelist));
                      list_del_init(&rq->flush.list);
                      blk_flush_restore_request(rq);
                      if (q->mq_ops)
                              blk_mq_end_request(rq, error);
                      else
                              __blk_end_request_all(rq, error);
                      break;
      
              default:
                      BUG();
              }
      
  388         kicked = blk_kick_flush(q, fq);
  388         return kicked | queued;
      }
      
      static void flush_end_io(struct request *flush_rq, int error)
      {
              struct request_queue *q = flush_rq->q;
              struct list_head *running;
              bool queued = false;
              struct request *rq, *n;
              unsigned long flags = 0;
              struct blk_flush_queue *fq = blk_get_flush_queue(q, flush_rq->mq_ctx);
      
              if (q->mq_ops) {
                      struct blk_mq_hw_ctx *hctx;
      
                      /* release the tag's ownership to the req cloned from */
                      spin_lock_irqsave(&fq->mq_flush_lock, flags);
                      hctx = blk_mq_map_queue(q, flush_rq->mq_ctx->cpu);
                      blk_mq_tag_set_rq(hctx, flush_rq->tag, fq->orig_rq);
                      flush_rq->tag = -1;
              }
      
              running = &fq->flush_queue[fq->flush_running_idx];
              BUG_ON(fq->flush_pending_idx == fq->flush_running_idx);
      
              /* account completion of the flush request */
              fq->flush_running_idx ^= 1;
      
              if (!q->mq_ops)
                      elv_completed_request(q, flush_rq);
      
              /* and push the waiting requests to the next stage */
              list_for_each_entry_safe(rq, n, running, flush.list) {
                      unsigned int seq = blk_flush_cur_seq(rq);
      
                      BUG_ON(seq != REQ_FSEQ_PREFLUSH && seq != REQ_FSEQ_POSTFLUSH);
                      queued |= blk_flush_complete_seq(rq, fq, seq, error);
              }
      
              /*
               * Kick the queue to avoid stall for two cases:
               * 1. Moving a request silently to empty queue_head may stall the
               * queue.
               * 2. When flush request is running in non-queueable queue, the
               * queue is hold. Restart the queue after flush request is finished
               * to avoid stall.
               * This function is called from request completion path and calling
               * directly into request_fn may confuse the driver.  Always use
               * kblockd.
               */
              if (queued || fq->flush_queue_delayed) {
                      WARN_ON(q->mq_ops);
                      blk_run_queue_async(q);
              }
              fq->flush_queue_delayed = 0;
              if (q->mq_ops)
                      spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
      }
      
      /**
       * blk_kick_flush - consider issuing flush request
       * @q: request_queue being kicked
       * @fq: flush queue
       *
       * Flush related states of @q have changed, consider issuing flush request.
       * Please read the comment at the top of this file for more info.
       *
       * CONTEXT:
       * spin_lock_irq(q->queue_lock or fq->mq_flush_lock)
       *
       * RETURNS:
       * %true if flush was issued, %false otherwise.
       */
      static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq)
      {
  388         struct list_head *pending = &fq->flush_queue[fq->flush_pending_idx];
              struct request *first_rq =
  348                 list_first_entry(pending, struct request, flush.list);
              struct request *flush_rq = fq->flush_rq;
      
              /* C1 described at the top of this file */
              if (fq->flush_pending_idx != fq->flush_running_idx || list_empty(pending))
                      return false;
      
              /* C2 and C3 */
  348         if (!list_empty(&fq->flush_data_in_flight) &&
                  time_before(jiffies,
                              fq->flush_pending_since + FLUSH_PENDING_TIMEOUT))
                      return false;
      
              /*
               * Issue flush and toggle pending_idx.  This makes pending_idx
               * different from running_idx, which means flush is in flight.
               */
              fq->flush_pending_idx ^= 1;
      
              blk_rq_init(q, flush_rq);
      
              /*
               * Borrow tag from the first request since they can't
               * be in flight at the same time. And acquire the tag's
               * ownership for flush req.
               */
              if (q->mq_ops) {
                      struct blk_mq_hw_ctx *hctx;
      
   23                 flush_rq->mq_ctx = first_rq->mq_ctx;
                      flush_rq->tag = first_rq->tag;
                      fq->orig_rq = first_rq;
      
                      hctx = blk_mq_map_queue(q, first_rq->mq_ctx->cpu);
                      blk_mq_tag_set_rq(hctx, first_rq->tag, flush_rq);
              }
      
  348         flush_rq->cmd_type = REQ_TYPE_FS;
              req_set_op_attrs(flush_rq, REQ_OP_FLUSH, WRITE_FLUSH | REQ_FLUSH_SEQ);
              flush_rq->rq_disk = first_rq->rq_disk;
              flush_rq->end_io = flush_end_io;
      
              return blk_flush_queue_rq(flush_rq, false);
      }
      
      static void flush_data_end_io(struct request *rq, int error)
      {
              struct request_queue *q = rq->q;
              struct blk_flush_queue *fq = blk_get_flush_queue(q, NULL);
      
              /*
               * Updating q->in_flight[] here for making this tag usable
               * early. Because in blk_queue_start_tag(),
               * q->in_flight[BLK_RW_ASYNC] is used to limit async I/O and
               * reserve tags for sync I/O.
               *
               * More importantly this way can avoid the following I/O
               * deadlock:
               *
               * - suppose there are 40 fua requests comming to flush queue
               *   and queue depth is 31
               * - 30 rqs are scheduled then blk_queue_start_tag() can't alloc
               *   tag for async I/O any more
               * - all the 30 rqs are completed before FLUSH_PENDING_TIMEOUT
               *   and flush_data_end_io() is called
               * - the other rqs still can't go ahead if not updating
               *   q->in_flight[BLK_RW_ASYNC] here, meantime these rqs
               *   are held in flush data queue and make no progress of
               *   handling post flush rq
               * - only after the post flush rq is handled, all these rqs
               *   can be completed
               */
      
              elv_completed_request(q, rq);
      
              /* for avoiding double accounting */
              rq->cmd_flags &= ~REQ_STARTED;
      
              /*
               * After populating an empty queue, kick it to avoid stall.  Read
               * the comment in flush_end_io().
               */
              if (blk_flush_complete_seq(rq, fq, REQ_FSEQ_DATA, error))
                      blk_run_queue_async(q);
      }
      
      static void mq_flush_data_end_io(struct request *rq, int error)
      {
              struct request_queue *q = rq->q;
              struct blk_mq_hw_ctx *hctx;
              struct blk_mq_ctx *ctx = rq->mq_ctx;
              unsigned long flags;
              struct blk_flush_queue *fq = blk_get_flush_queue(q, ctx);
      
              hctx = blk_mq_map_queue(q, ctx->cpu);
      
              /*
               * After populating an empty queue, kick it to avoid stall.  Read
               * the comment in flush_end_io().
               */
              spin_lock_irqsave(&fq->mq_flush_lock, flags);
              if (blk_flush_complete_seq(rq, fq, REQ_FSEQ_DATA, error))
                      blk_mq_run_hw_queue(hctx, true);
              spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
      }
      
      /**
       * blk_insert_flush - insert a new FLUSH/FUA request
       * @rq: request to insert
       *
       * To be called from __elv_add_request() for %ELEVATOR_INSERT_FLUSH insertions.
       * or __blk_mq_run_hw_queue() to dispatch request.
       * @rq is being submitted.  Analyze what needs to be done and put it on the
       * right queue.
       *
       * CONTEXT:
       * spin_lock_irq(q->queue_lock) in !mq case
       */
      void blk_insert_flush(struct request *rq)
      {
  389         struct request_queue *q = rq->q;
              unsigned long fflags = q->queue_flags;        /* may change, cache */
  389         unsigned int policy = blk_flush_policy(fflags, rq);
  389         struct blk_flush_queue *fq = blk_get_flush_queue(q, rq->mq_ctx);
      
              /*
               * @policy now records what operations need to be done.  Adjust
               * REQ_PREFLUSH and FUA for the driver.
               */
              rq->cmd_flags &= ~REQ_PREFLUSH;
  389         if (!(fflags & (1UL << QUEUE_FLAG_FUA)))
  389                 rq->cmd_flags &= ~REQ_FUA;
      
              /*
               * An empty flush handed down from a stacking driver may
               * translate into nothing if the underlying device does not
               * advertise a write-back cache.  In this case, simply
               * complete the request.
               */
  389         if (!policy) {
                      if (q->mq_ops)
                              blk_mq_end_request(rq, 0);
                      else
                              __blk_end_bidi_request(rq, 0, 0, 0);
                      return;
              }
      
  389         BUG_ON(rq->bio != rq->biotail); /*assumes zero or single bio rq */
      
              /*
               * If there's data but flush is not necessary, the request can be
               * processed directly without going through flush machinery.  Queue
               * for normal execution.
               */
  389         if ((policy & REQ_FSEQ_DATA) &&
                  !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
                      if (q->mq_ops) {
                              blk_mq_insert_request(rq, false, false, true);
                      } else
                              list_add_tail(&rq->queuelist, &q->queue_head);
                      return;
              }
      
              /*
               * @rq should go through flush machinery.  Mark it part of flush
               * sequence and submit for further processing.
               */
  389         memset(&rq->flush, 0, sizeof(rq->flush));
              INIT_LIST_HEAD(&rq->flush.list);
              rq->cmd_flags |= REQ_FLUSH_SEQ;
              rq->flush.saved_end_io = rq->end_io; /* Usually NULL */
              if (q->mq_ops) {
   34                 rq->end_io = mq_flush_data_end_io;
      
                      spin_lock_irq(&fq->mq_flush_lock);
                      blk_flush_complete_seq(rq, fq, REQ_FSEQ_ACTIONS & ~policy, 0);
                      spin_unlock_irq(&fq->mq_flush_lock);
  388                 return;
              }
  355         rq->end_io = flush_data_end_io;
      
              blk_flush_complete_seq(rq, fq, REQ_FSEQ_ACTIONS & ~policy, 0);
      }
      
      /**
       * blkdev_issue_flush - queue a flush
       * @bdev:        blockdev to issue flush for
       * @gfp_mask:        memory allocation flags (for bio_alloc)
       * @error_sector:        error sector
       *
       * Description:
       *    Issue a flush for the block device in question. Caller can supply
       *    room for storing the error offset in case of a flush error, if they
       *    wish to. If WAIT flag is not passed then caller may check only what
       *    request was pushed in some internal queue for later handling.
       */
      int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
                      sector_t *error_sector)
      {
              struct request_queue *q;
              struct bio *bio;
              int ret = 0;
      
  349         if (bdev->bd_disk == NULL)
                      return -ENXIO;
      
  349         q = bdev_get_queue(bdev);
              if (!q)
                      return -ENXIO;
      
              /*
               * some block devices may not have their queue correctly set up here
               * (e.g. loop device without a backing file) and so issuing a flush
               * here will panic. Ensure there is a request function before issuing
               * the flush.
               */
  349         if (!q->make_request_fn)
                      return -ENXIO;
      
  349         bio = bio_alloc(gfp_mask, 0);
              bio->bi_bdev = bdev;
              bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
      
              ret = submit_bio_wait(bio);
      
              /*
               * The driver must store the error location in ->bi_sector, if
               * it supports it. For non-stacked drivers, this should be
               * copied from blk_rq_pos(rq).
               */
              if (error_sector)
                      *error_sector = bio->bi_iter.bi_sector;
      
  348         bio_put(bio);
  348         return ret;
      }
      EXPORT_SYMBOL(blkdev_issue_flush);
      
      struct blk_flush_queue *blk_alloc_flush_queue(struct request_queue *q,
                      int node, int cmd_size)
      {
              struct blk_flush_queue *fq;
              int rq_sz = sizeof(struct request);
      
   26         fq = kzalloc_node(sizeof(*fq), GFP_KERNEL, node);
              if (!fq)
                      goto fail;
      
   26         if (q->mq_ops) {
   26                 spin_lock_init(&fq->mq_flush_lock);
                      rq_sz = round_up(rq_sz + cmd_size, cache_line_size());
              }
      
   26         fq->flush_rq = kzalloc_node(rq_sz, GFP_KERNEL, node);
              if (!fq->flush_rq)
                      goto fail_rq;
      
   26         INIT_LIST_HEAD(&fq->flush_queue[0]);
              INIT_LIST_HEAD(&fq->flush_queue[1]);
              INIT_LIST_HEAD(&fq->flush_data_in_flight);
      
   26         return fq;
      
       fail_rq:
              kfree(fq);
       fail:
              return NULL;
      }
      
      void blk_free_flush_queue(struct blk_flush_queue *fq)
      {
              /* bio based request queue hasn't flush queue */
   46         if (!fq)
                      return;
      
   46         kfree(fq->flush_rq);
   46         kfree(fq);
      }
      /*
       * User-space I/O driver support for HID subsystem
       * Copyright (c) 2012 David Herrmann
       */
      
      /*
       * This program is free software; you can redistribute it and/or modify it
       * under the terms of the GNU General Public License as published by the Free
       * Software Foundation; either version 2 of the License, or (at your option)
       * any later version.
       */
      
      #include <linux/atomic.h>
      #include <linux/compat.h>
      #include <linux/cred.h>
      #include <linux/device.h>
      #include <linux/fs.h>
      #include <linux/hid.h>
      #include <linux/input.h>
      #include <linux/miscdevice.h>
      #include <linux/module.h>
      #include <linux/mutex.h>
      #include <linux/poll.h>
      #include <linux/sched.h>
      #include <linux/spinlock.h>
      #include <linux/uhid.h>
      #include <linux/wait.h>
      #include <linux/uaccess.h>
      
      #define UHID_NAME        "uhid"
      #define UHID_BUFSIZE        32
      
      static DEFINE_MUTEX(uhid_open_mutex);
      
      struct uhid_device {
              struct mutex devlock;
              bool running;
      
              __u8 *rd_data;
              uint rd_size;
      
              struct hid_device *hid;
              struct uhid_event input_buf;
      
              wait_queue_head_t waitq;
              spinlock_t qlock;
              __u8 head;
              __u8 tail;
              struct uhid_event *outq[UHID_BUFSIZE];
      
              /* blocking GET_REPORT support; state changes protected by qlock */
              struct mutex report_lock;
              wait_queue_head_t report_wait;
              bool report_running;
              u32 report_id;
              u32 report_type;
              struct uhid_event report_buf;
              struct work_struct worker;
      };
      
      static struct miscdevice uhid_misc;
      
      static void uhid_device_add_worker(struct work_struct *work)
      {
              struct uhid_device *uhid = container_of(work, struct uhid_device, worker);
              int ret;
      
              ret = hid_add_device(uhid->hid);
              if (ret) {
                      hid_err(uhid->hid, "Cannot register HID device: error %d\n", ret);
      
                      hid_destroy_device(uhid->hid);
                      uhid->hid = NULL;
                      uhid->running = false;
              }
      }
      
      static void uhid_queue(struct uhid_device *uhid, struct uhid_event *ev)
      {
              __u8 newhead;
      
    7         newhead = (uhid->head + 1) % UHID_BUFSIZE;
      
              if (newhead != uhid->tail) {
    7                 uhid->outq[uhid->head] = ev;
                      uhid->head = newhead;
                      wake_up_interruptible(&uhid->waitq);
              } else {
                      hid_warn(uhid->hid, "Output queue is full\n");
                      kfree(ev);
              }
    7 }
      
      static int uhid_queue_event(struct uhid_device *uhid, __u32 event)
      {
              unsigned long flags;
              struct uhid_event *ev;
      
    7         ev = kzalloc(sizeof(*ev), GFP_KERNEL);
              if (!ev)
                      return -ENOMEM;
      
    7         ev->type = event;
      
              spin_lock_irqsave(&uhid->qlock, flags);
              uhid_queue(uhid, ev);
              spin_unlock_irqrestore(&uhid->qlock, flags);
      
    7         return 0;
      }
      
      static int uhid_hid_start(struct hid_device *hid)
      {
              struct uhid_device *uhid = hid->driver_data;
              struct uhid_event *ev;
              unsigned long flags;
      
              ev = kzalloc(sizeof(*ev), GFP_KERNEL);
              if (!ev)
                      return -ENOMEM;
      
              ev->type = UHID_START;
      
              if (hid->report_enum[HID_FEATURE_REPORT].numbered)
                      ev->u.start.dev_flags |= UHID_DEV_NUMBERED_FEATURE_REPORTS;
              if (hid->report_enum[HID_OUTPUT_REPORT].numbered)
                      ev->u.start.dev_flags |= UHID_DEV_NUMBERED_OUTPUT_REPORTS;
              if (hid->report_enum[HID_INPUT_REPORT].numbered)
                      ev->u.start.dev_flags |= UHID_DEV_NUMBERED_INPUT_REPORTS;
      
              spin_lock_irqsave(&uhid->qlock, flags);
              uhid_queue(uhid, ev);
              spin_unlock_irqrestore(&uhid->qlock, flags);
      
              return 0;
      }
      
      static void uhid_hid_stop(struct hid_device *hid)
      {
    7         struct uhid_device *uhid = hid->driver_data;
      
              hid->claimed = 0;
              uhid_queue_event(uhid, UHID_STOP);
      }
      
      static int uhid_hid_open(struct hid_device *hid)
      {
              struct uhid_device *uhid = hid->driver_data;
              int retval = 0;
      
              mutex_lock(&uhid_open_mutex);
              if (!hid->open++) {
                      retval = uhid_queue_event(uhid, UHID_OPEN);
                      if (retval)
                              hid->open--;
              }
              mutex_unlock(&uhid_open_mutex);
              return retval;
      }
      
      static void uhid_hid_close(struct hid_device *hid)
      {
              struct uhid_device *uhid = hid->driver_data;
      
              mutex_lock(&uhid_open_mutex);
              if (!--hid->open)
                      uhid_queue_event(uhid, UHID_CLOSE);
              mutex_unlock(&uhid_open_mutex);
      }
      
      static int uhid_hid_parse(struct hid_device *hid)
      {
              struct uhid_device *uhid = hid->driver_data;
      
              return hid_parse_report(hid, uhid->rd_data, uhid->rd_size);
      }
      
      /* must be called with report_lock held */
      static int __uhid_report_queue_and_wait(struct uhid_device *uhid,
                                              struct uhid_event *ev,
                                              __u32 *report_id)
      {
              unsigned long flags;
              int ret;
      
              spin_lock_irqsave(&uhid->qlock, flags);
              *report_id = ++uhid->report_id;
              uhid->report_type = ev->type + 1;
              uhid->report_running = true;
              uhid_queue(uhid, ev);
              spin_unlock_irqrestore(&uhid->qlock, flags);
      
              ret = wait_event_interruptible_timeout(uhid->report_wait,
                                      !uhid->report_running || !uhid->running,
                                      5 * HZ);
              if (!ret || !uhid->running || uhid->report_running)
                      ret = -EIO;
              else if (ret < 0)
                      ret = -ERESTARTSYS;
              else
                      ret = 0;
      
              uhid->report_running = false;
      
              return ret;
      }
      
      static void uhid_report_wake_up(struct uhid_device *uhid, u32 id,
                                      const struct uhid_event *ev)
      {
              unsigned long flags;
      
    4         spin_lock_irqsave(&uhid->qlock, flags);
      
              /* id for old report; drop it silently */
              if (uhid->report_type != ev->type || uhid->report_id != id)
                      goto unlock;
              if (!uhid->report_running)
                      goto unlock;
      
              memcpy(&uhid->report_buf, ev, sizeof(*ev));
              uhid->report_running = false;
              wake_up_interruptible(&uhid->report_wait);
      
      unlock:
    4         spin_unlock_irqrestore(&uhid->qlock, flags);
      }
      
      static int uhid_hid_get_report(struct hid_device *hid, unsigned char rnum,
                                     u8 *buf, size_t count, u8 rtype)
      {
              struct uhid_device *uhid = hid->driver_data;
              struct uhid_get_report_reply_req *req;
              struct uhid_event *ev;
              int ret;
      
              if (!uhid->running)
                      return -EIO;
      
              ev = kzalloc(sizeof(*ev), GFP_KERNEL);
              if (!ev)
                      return -ENOMEM;
      
              ev->type = UHID_GET_REPORT;
              ev->u.get_report.rnum = rnum;
              ev->u.get_report.rtype = rtype;
      
              ret = mutex_lock_interruptible(&uhid->report_lock);
              if (ret) {
                      kfree(ev);
                      return ret;
              }
      
              /* this _always_ takes ownership of @ev */
              ret = __uhid_report_queue_and_wait(uhid, ev, &ev->u.get_report.id);
              if (ret)
                      goto unlock;
      
              req = &uhid->report_buf.u.get_report_reply;
              if (req->err) {
                      ret = -EIO;
              } else {
                      ret = min3(count, (size_t)req->size, (size_t)UHID_DATA_MAX);
                      memcpy(buf, req->data, ret);
              }
      
      unlock:
              mutex_unlock(&uhid->report_lock);
              return ret;
      }
      
      static int uhid_hid_set_report(struct hid_device *hid, unsigned char rnum,
                                     const u8 *buf, size_t count, u8 rtype)
      {
              struct uhid_device *uhid = hid->driver_data;
              struct uhid_event *ev;
              int ret;
      
              if (!uhid->running || count > UHID_DATA_MAX)
                      return -EIO;
      
              ev = kzalloc(sizeof(*ev), GFP_KERNEL);
              if (!ev)
                      return -ENOMEM;
      
              ev->type = UHID_SET_REPORT;
              ev->u.set_report.rnum = rnum;
              ev->u.set_report.rtype = rtype;
              ev->u.set_report.size = count;
              memcpy(ev->u.set_report.data, buf, count);
      
              ret = mutex_lock_interruptible(&uhid->report_lock);
              if (ret) {
                      kfree(ev);
                      return ret;
              }
      
              /* this _always_ takes ownership of @ev */
              ret = __uhid_report_queue_and_wait(uhid, ev, &ev->u.set_report.id);
              if (ret)
                      goto unlock;
      
              if (uhid->report_buf.u.set_report_reply.err)
                      ret = -EIO;
              else
                      ret = count;
      
      unlock:
              mutex_unlock(&uhid->report_lock);
              return ret;
      }
      
      static int uhid_hid_raw_request(struct hid_device *hid, unsigned char reportnum,
                                      __u8 *buf, size_t len, unsigned char rtype,
                                      int reqtype)
      {
              u8 u_rtype;
      
              switch (rtype) {
              case HID_FEATURE_REPORT:
                      u_rtype = UHID_FEATURE_REPORT;
                      break;
              case HID_OUTPUT_REPORT:
                      u_rtype = UHID_OUTPUT_REPORT;
                      break;
              case HID_INPUT_REPORT:
                      u_rtype = UHID_INPUT_REPORT;
                      break;
              default:
                      return -EINVAL;
              }
      
              switch (reqtype) {
              case HID_REQ_GET_REPORT:
                      return uhid_hid_get_report(hid, reportnum, buf, len, u_rtype);
              case HID_REQ_SET_REPORT:
                      return uhid_hid_set_report(hid, reportnum, buf, len, u_rtype);
              default:
                      return -EIO;
              }
      }
      
      static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
                                     unsigned char report_type)
      {
              struct uhid_device *uhid = hid->driver_data;
              __u8 rtype;
              unsigned long flags;
              struct uhid_event *ev;
      
              switch (report_type) {
              case HID_FEATURE_REPORT:
                      rtype = UHID_FEATURE_REPORT;
                      break;
              case HID_OUTPUT_REPORT:
                      rtype = UHID_OUTPUT_REPORT;
                      break;
              default:
                      return -EINVAL;
              }
      
              if (count < 1 || count > UHID_DATA_MAX)
                      return -EINVAL;
      
              ev = kzalloc(sizeof(*ev), GFP_KERNEL);
              if (!ev)
                      return -ENOMEM;
      
              ev->type = UHID_OUTPUT;
              ev->u.output.size = count;
              ev->u.output.rtype = rtype;
              memcpy(ev->u.output.data, buf, count);
      
              spin_lock_irqsave(&uhid->qlock, flags);
              uhid_queue(uhid, ev);
              spin_unlock_irqrestore(&uhid->qlock, flags);
      
              return count;
      }
      
      static int uhid_hid_output_report(struct hid_device *hid, __u8 *buf,
                                        size_t count)
      {
              return uhid_hid_output_raw(hid, buf, count, HID_OUTPUT_REPORT);
      }
      
      static struct hid_ll_driver uhid_hid_driver = {
              .start = uhid_hid_start,
              .stop = uhid_hid_stop,
              .open = uhid_hid_open,
              .close = uhid_hid_close,
              .parse = uhid_hid_parse,
              .raw_request = uhid_hid_raw_request,
              .output_report = uhid_hid_output_report,
      };
      
      #ifdef CONFIG_COMPAT
      
      /* Apparently we haven't stepped on these rakes enough times yet. */
      struct uhid_create_req_compat {
              __u8 name[128];
              __u8 phys[64];
              __u8 uniq[64];
      
              compat_uptr_t rd_data;
              __u16 rd_size;
      
              __u16 bus;
              __u32 vendor;
              __u32 product;
              __u32 version;
              __u32 country;
      } __attribute__((__packed__));
      
      static int uhid_event_from_user(const char __user *buffer, size_t len,
                                      struct uhid_event *event)
      {
              if (in_compat_syscall()) {
                      u32 type;
      
                      if (get_user(type, buffer))
                              return -EFAULT;
      
                      if (type == UHID_CREATE) {
                              /*
                               * This is our messed up request with compat pointer.
                               * It is largish (more than 256 bytes) so we better
                               * allocate it from the heap.
                               */
                              struct uhid_create_req_compat *compat;
      
                              compat = kzalloc(sizeof(*compat), GFP_KERNEL);
                              if (!compat)
                                      return -ENOMEM;
      
                              buffer += sizeof(type);
                              len -= sizeof(type);
                              if (copy_from_user(compat, buffer,
                                                 min(len, sizeof(*compat)))) {
                                      kfree(compat);
                                      return -EFAULT;
                              }
      
                              /* Shuffle the data over to proper structure */
                              event->type = type;
      
                              memcpy(event->u.create.name, compat->name,
                                      sizeof(compat->name));
                              memcpy(event->u.create.phys, compat->phys,
                                      sizeof(compat->phys));
                              memcpy(event->u.create.uniq, compat->uniq,
                                      sizeof(compat->uniq));
      
                              event->u.create.rd_data = compat_ptr(compat->rd_data);
                              event->u.create.rd_size = compat->rd_size;
      
                              event->u.create.bus = compat->bus;
                              event->u.create.vendor = compat->vendor;
                              event->u.create.product = compat->product;
                              event->u.create.version = compat->version;
                              event->u.create.country = compat->country;
      
                              kfree(compat);
                              return 0;
                      }
                      /* All others can be copied directly */
              }
      
   38         if (copy_from_user(event, buffer, min(len, sizeof(*event))))
                      return -EFAULT;
      
              return 0;
      }
      #else
      static int uhid_event_from_user(const char __user *buffer, size_t len,
                                      struct uhid_event *event)
      {
              if (copy_from_user(event, buffer, min(len, sizeof(*event))))
                      return -EFAULT;
      
              return 0;
      }
      #endif
      
      static int uhid_dev_create2(struct uhid_device *uhid,
                                  const struct uhid_event *ev)
      {
              struct hid_device *hid;
              size_t rd_size, len;
              void *rd_data;
              int ret;
      
   16         if (uhid->running)
                      return -EALREADY;
      
   16         rd_size = ev->u.create2.rd_size;
              if (rd_size <= 0 || rd_size > HID_MAX_DESCRIPTOR_SIZE)
                      return -EINVAL;
      
   14         rd_data = kmemdup(ev->u.create2.rd_data, rd_size, GFP_KERNEL);
              if (!rd_data)
                      return -ENOMEM;
      
   14         uhid->rd_size = rd_size;
              uhid->rd_data = rd_data;
      
              hid = hid_allocate_device();
              if (IS_ERR(hid)) {
                      ret = PTR_ERR(hid);
                      goto err_free;
              }
      
              len = min(sizeof(hid->name), sizeof(ev->u.create2.name)) - 1;
   11         strncpy(hid->name, ev->u.create2.name, len);
              len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)) - 1;
              strncpy(hid->phys, ev->u.create2.phys, len);
              len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)) - 1;
              strncpy(hid->uniq, ev->u.create2.uniq, len);
      
              hid->ll_driver = &uhid_hid_driver;
              hid->bus = ev->u.create2.bus;
              hid->vendor = ev->u.create2.vendor;
              hid->product = ev->u.create2.product;
              hid->version = ev->u.create2.version;
              hid->country = ev->u.create2.country;
              hid->driver_data = uhid;
              hid->dev.parent = uhid_misc.this_device;
      
              uhid->hid = hid;
              uhid->running = true;
      
              /* Adding of a HID device is done through a worker, to allow HID drivers
               * which use feature requests during .probe to work, without they would
               * be blocked on devlock, which is held by uhid_char_write.
               */
              schedule_work(&uhid->worker);
      
   13         return 0;
      
      err_free:
              kfree(uhid->rd_data);
              uhid->rd_data = NULL;
              uhid->rd_size = 0;
              return ret;
      }
      
      static int uhid_dev_create(struct uhid_device *uhid,
                                 struct uhid_event *ev)
      {
              struct uhid_create_req orig;
      
    8         orig = ev->u.create;
      
              if (orig.rd_size <= 0 || orig.rd_size > HID_MAX_DESCRIPTOR_SIZE)
                      return -EINVAL;
    6         if (copy_from_user(&ev->u.create2.rd_data, orig.rd_data, orig.rd_size))
                      return -EFAULT;
      
    5         memcpy(ev->u.create2.name, orig.name, sizeof(orig.name));
              memcpy(ev->u.create2.phys, orig.phys, sizeof(orig.phys));
              memcpy(ev->u.create2.uniq, orig.uniq, sizeof(orig.uniq));
              ev->u.create2.rd_size = orig.rd_size;
              ev->u.create2.bus = orig.bus;
              ev->u.create2.vendor = orig.vendor;
              ev->u.create2.product = orig.product;
              ev->u.create2.version = orig.version;
              ev->u.create2.country = orig.country;
      
    7         return uhid_dev_create2(uhid, ev);
      }
      
      static int uhid_dev_destroy(struct uhid_device *uhid)
      {
   12         if (!uhid->running)
                      return -EINVAL;
      
    9         uhid->running = false;
              wake_up_interruptible(&uhid->report_wait);
      
              cancel_work_sync(&uhid->worker);
      
              hid_destroy_device(uhid->hid);
              kfree(uhid->rd_data);
      
   10         return 0;
      }
      
      static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev)
      {
              if (!uhid->running)
                      return -EINVAL;
      
              hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input.data,
    4                          min_t(size_t, ev->u.input.size, UHID_DATA_MAX), 0);
      
              return 0;
      }
      
      static int uhid_dev_input2(struct uhid_device *uhid, struct uhid_event *ev)
      {
              if (!uhid->running)
                      return -EINVAL;
      
              hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input2.data,
    4                          min_t(size_t, ev->u.input2.size, UHID_DATA_MAX), 0);
      
              return 0;
      }
      
      static int uhid_dev_get_report_reply(struct uhid_device *uhid,
                                           struct uhid_event *ev)
      {
    3         if (!uhid->running)
                      return -EINVAL;
      
    2         uhid_report_wake_up(uhid, ev->u.get_report_reply.id, ev);
              return 0;
      }
      
      static int uhid_dev_set_report_reply(struct uhid_device *uhid,
                                           struct uhid_event *ev)
      {
    3         if (!uhid->running)
                      return -EINVAL;
      
    2         uhid_report_wake_up(uhid, ev->u.set_report_reply.id, ev);
              return 0;
      }
      
      static int uhid_char_open(struct inode *inode, struct file *file)
      {
              struct uhid_device *uhid;
      
    4         uhid = kzalloc(sizeof(*uhid), GFP_KERNEL);
              if (!uhid)
                      return -ENOMEM;
      
    4         mutex_init(&uhid->devlock);
              mutex_init(&uhid->report_lock);
              spin_lock_init(&uhid->qlock);
              init_waitqueue_head(&uhid->waitq);
              init_waitqueue_head(&uhid->report_wait);
              uhid->running = false;
              INIT_WORK(&uhid->worker, uhid_device_add_worker);
      
              file->private_data = uhid;
              nonseekable_open(inode, file);
      
    4         return 0;
      }
      
      static int uhid_char_release(struct inode *inode, struct file *file)
      {
    5         struct uhid_device *uhid = file->private_data;
              unsigned int i;
      
              uhid_dev_destroy(uhid);
      
              for (i = 0; i < UHID_BUFSIZE; ++i)
    5                 kfree(uhid->outq[i]);
      
    5         kfree(uhid);
      
              return 0;
      }
      
      static ssize_t uhid_char_read(struct file *file, char __user *buffer,
                                      size_t count, loff_t *ppos)
      {
    8         struct uhid_device *uhid = file->private_data;
              int ret;
              unsigned long flags;
              size_t len;
      
              /* they need at least the "type" member of uhid_event */
              if (count < sizeof(__u32))
                      return -EINVAL;
      
      try_again:
    7         if (file->f_flags & O_NONBLOCK) {
    2                 if (uhid->head == uhid->tail)
                              return -EAGAIN;
              } else {
    5                 ret = wait_event_interruptible(uhid->waitq,
                                                      uhid->head != uhid->tail);
                      if (ret)
    2                         return ret;
              }
      
    4         ret = mutex_lock_interruptible(&uhid->devlock);
              if (ret)
    7                 return ret;
      
    4         if (uhid->head == uhid->tail) {
    1                 mutex_unlock(&uhid->devlock);
                      goto try_again;
              } else {
    4                 len = min(count, sizeof(**uhid->outq));
                      if (copy_to_user(buffer, uhid->outq[uhid->tail], len)) {
                              ret = -EFAULT;
                      } else {
    3                         kfree(uhid->outq[uhid->tail]);
                              uhid->outq[uhid->tail] = NULL;
      
                              spin_lock_irqsave(&uhid->qlock, flags);
                              uhid->tail = (uhid->tail + 1) % UHID_BUFSIZE;
                              spin_unlock_irqrestore(&uhid->qlock, flags);
                      }
              }
      
    1         mutex_unlock(&uhid->devlock);
              return ret ? ret : len;
      }
      
      static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
                                      size_t count, loff_t *ppos)
      {
   38         struct uhid_device *uhid = file->private_data;
              int ret;
              size_t len;
      
              /* we need at least the "type" member of uhid_event */
              if (count < sizeof(__u32))
                      return -EINVAL;
      
   38         ret = mutex_lock_interruptible(&uhid->devlock);
   34         if (ret)
                      return ret;
      
   38         memset(&uhid->input_buf, 0, sizeof(uhid->input_buf));
              len = min(count, sizeof(uhid->input_buf));
      
   38         ret = uhid_event_from_user(buffer, len, &uhid->input_buf);
              if (ret)
                      goto unlock;
      
   38         switch (uhid->input_buf.type) {
              case UHID_CREATE:
                      /*
                       * 'struct uhid_create_req' contains a __user pointer which is
                       * copied from, so it's unsafe to allow this with elevated
                       * privileges (e.g. from a setuid binary) or via kernel_write().
                       */
   10                 if (file->f_cred != current_cred() || uaccess_kernel()) {
    2                         pr_err_once("UHID_CREATE from different security context by process %d (%s), this is not allowed.\n",
                                          task_tgid_vnr(current), current->comm);
                              ret = -EACCES;
                              goto unlock;
                      }
    8                 ret = uhid_dev_create(uhid, &uhid->input_buf);
                      break;
              case UHID_CREATE2:
   11                 ret = uhid_dev_create2(uhid, &uhid->input_buf);
                      break;
              case UHID_DESTROY:
    7                 ret = uhid_dev_destroy(uhid);
                      break;
              case UHID_INPUT:
    6                 ret = uhid_dev_input(uhid, &uhid->input_buf);
                      break;
              case UHID_INPUT2:
    5                 ret = uhid_dev_input2(uhid, &uhid->input_buf);
                      break;
              case UHID_GET_REPORT_REPLY:
    3                 ret = uhid_dev_get_report_reply(uhid, &uhid->input_buf);
                      break;
              case UHID_SET_REPORT_REPLY:
    3                 ret = uhid_dev_set_report_reply(uhid, &uhid->input_buf);
                      break;
              default:
                      ret = -EOPNOTSUPP;
              }
      
      unlock:
   27         mutex_unlock(&uhid->devlock);
      
              /* return "count" not "len" to not confuse the caller */
   26         return ret ? ret : count;
      }
      
      static unsigned int uhid_char_poll(struct file *file, poll_table *wait)
      {
    9         struct uhid_device *uhid = file->private_data;
      
    9         poll_wait(file, &uhid->waitq, wait);
      
    9         if (uhid->head != uhid->tail)
    9                 return POLLIN | POLLRDNORM;
      
              return 0;
      }
      
      static const struct file_operations uhid_fops = {
              .owner                = THIS_MODULE,
              .open                = uhid_char_open,
              .release        = uhid_char_release,
              .read                = uhid_char_read,
              .write                = uhid_char_write,
              .poll                = uhid_char_poll,
              .llseek                = no_llseek,
      };
      
      static struct miscdevice uhid_misc = {
              .fops                = &uhid_fops,
              .minor                = UHID_MINOR,
              .name                = UHID_NAME,
      };
      module_misc_device(uhid_misc);
      
      MODULE_LICENSE("GPL");
      MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
      MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem");
      MODULE_ALIAS_MISCDEV(UHID_MINOR);
      MODULE_ALIAS("devname:" UHID_NAME);
      /*
       *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
       *
       * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
       * which can be dynamically activated and de-activated by the line
       * discipline handling modules (like SLIP).
       */
      
      #include <linux/types.h>
      #include <linux/termios.h>
      #include <linux/errno.h>
      #include <linux/sched.h>
      #include <linux/kernel.h>
      #include <linux/major.h>
      #include <linux/tty.h>
      #include <linux/fcntl.h>
      #include <linux/string.h>
      #include <linux/mm.h>
      #include <linux/module.h>
      #include <linux/bitops.h>
      #include <linux/mutex.h>
      #include <linux/compat.h>
      
      #include <asm/io.h>
      #include <asm/uaccess.h>
      
      #undef TTY_DEBUG_WAIT_UNTIL_SENT
      
      #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
      # define tty_debug_wait_until_sent(tty, f, args...)    tty_debug(tty, f, ##args)
      #else
      # define tty_debug_wait_until_sent(tty, f, args...)    do {} while (0)
      #endif
      
      #undef        DEBUG
      
      /*
       * Internal flag options for termios setting behavior
       */
      #define TERMIOS_FLUSH        1
      #define TERMIOS_WAIT        2
      #define TERMIOS_TERMIO        4
      #define TERMIOS_OLD        8
      
      
      /**
       *        tty_chars_in_buffer        -        characters pending
       *        @tty: terminal
       *
       *        Return the number of bytes of data in the device private
       *        output queue. If no private method is supplied there is assumed
       *        to be no queue on the device.
       */
      
      int tty_chars_in_buffer(struct tty_struct *tty)
      {
   56         if (tty->ops->chars_in_buffer)
  106                 return tty->ops->chars_in_buffer(tty);
              else
                      return 0;
      }
      EXPORT_SYMBOL(tty_chars_in_buffer);
      
      /**
       *        tty_write_room                -        write queue space
       *        @tty: terminal
       *
       *        Return the number of bytes that can be queued to this device
       *        at the present time. The result should be treated as a guarantee
       *        and the driver cannot offer a value it later shrinks by more than
       *        the number of bytes written. If no method is provided 2K is always
       *        returned and data may be lost as there will be no flow control.
       */
       
      int tty_write_room(struct tty_struct *tty)
      {
  135         if (tty->ops->write_room)
  135                 return tty->ops->write_room(tty);
              return 2048;
      }
      EXPORT_SYMBOL(tty_write_room);
      
      /**
       *        tty_driver_flush_buffer        -        discard internal buffer
       *        @tty: terminal
       *
       *        Discard the internal output buffer for this device. If no method
       *        is provided then either the buffer cannot be hardware flushed or
       *        there is no buffer driver side.
       */
      void tty_driver_flush_buffer(struct tty_struct *tty)
      {
   59         if (tty->ops->flush_buffer)
   59                 tty->ops->flush_buffer(tty);
   55 }
      EXPORT_SYMBOL(tty_driver_flush_buffer);
      
      /**
       *        tty_throttle                -        flow control
       *        @tty: terminal
       *
       *        Indicate that a tty should stop transmitting data down the stack.
       *        Takes the termios rwsem to protect against parallel throttle/unthrottle
       *        and also to ensure the driver can consistently reference its own
       *        termios data at this point when implementing software flow control.
       */
      
      void tty_throttle(struct tty_struct *tty)
      {
              down_write(&tty->termios_rwsem);
              /* check TTY_THROTTLED first so it indicates our state */
              if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
                  tty->ops->throttle)
                      tty->ops->throttle(tty);
              tty->flow_change = 0;
              up_write(&tty->termios_rwsem);
      }
      EXPORT_SYMBOL(tty_throttle);
      
      /**
       *        tty_unthrottle                -        flow control
       *        @tty: terminal
       *
       *        Indicate that a tty may continue transmitting data down the stack.
       *        Takes the termios rwsem to protect against parallel throttle/unthrottle
       *        and also to ensure the driver can consistently reference its own
       *        termios data at this point when implementing software flow control.
       *
       *        Drivers should however remember that the stack can issue a throttle,
       *        then change flow control method, then unthrottle.
       */
      
      void tty_unthrottle(struct tty_struct *tty)
      {
  101         down_write(&tty->termios_rwsem);
              if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
   13             tty->ops->unthrottle)
   13                 tty->ops->unthrottle(tty);
  101         tty->flow_change = 0;
              up_write(&tty->termios_rwsem);
      }
      EXPORT_SYMBOL(tty_unthrottle);
      
      /**
       *        tty_throttle_safe        -        flow control
       *        @tty: terminal
       *
       *        Similar to tty_throttle() but will only attempt throttle
       *        if tty->flow_change is TTY_THROTTLE_SAFE. Prevents an accidental
       *        throttle due to race conditions when throttling is conditional
       *        on factors evaluated prior to throttling.
       *
       *        Returns 0 if tty is throttled (or was already throttled)
       */
      
      int tty_throttle_safe(struct tty_struct *tty)
      {
              int ret = 0;
      
              mutex_lock(&tty->throttle_mutex);
              if (!tty_throttled(tty)) {
                      if (tty->flow_change != TTY_THROTTLE_SAFE)
                              ret = 1;
                      else {
                              set_bit(TTY_THROTTLED, &tty->flags);
                              if (tty->ops->throttle)
                                      tty->ops->throttle(tty);
                      }
              }
              mutex_unlock(&tty->throttle_mutex);
      
              return ret;
      }
      
      /**
       *        tty_unthrottle_safe        -        flow control
       *        @tty: terminal
       *
       *        Similar to tty_unthrottle() but will only attempt unthrottle
       *        if tty->flow_change is TTY_UNTHROTTLE_SAFE. Prevents an accidental
       *        unthrottle due to race conditions when unthrottling is conditional
       *        on factors evaluated prior to unthrottling.
       *
       *        Returns 0 if tty is unthrottled (or was already unthrottled)
       */
      
      int tty_unthrottle_safe(struct tty_struct *tty)
      {
              int ret = 0;
      
    2         mutex_lock(&tty->throttle_mutex);
              if (tty_throttled(tty)) {
    2                 if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
                              ret = 1;
                      else {
    2                         clear_bit(TTY_THROTTLED, &tty->flags);
                              if (tty->ops->unthrottle)
    2                                 tty->ops->unthrottle(tty);
                      }
              }
    2         mutex_unlock(&tty->throttle_mutex);
      
              return ret;
      }
      
      /**
       *        tty_wait_until_sent        -        wait for I/O to finish
       *        @tty: tty we are waiting for
       *        @timeout: how long we will wait
       *
       *        Wait for characters pending in a tty driver to hit the wire, or
       *        for a timeout to occur (eg due to flow control)
       *
       *        Locking: none
       */
      
      void tty_wait_until_sent(struct tty_struct *tty, long timeout)
      {
              tty_debug_wait_until_sent(tty, "wait until sent, timeout=%ld\n", timeout);
      
   53         if (!timeout)
                      timeout = MAX_SCHEDULE_TIMEOUT;
      
   53         timeout = wait_event_interruptible_timeout(tty->write_wait,
                              !tty_chars_in_buffer(tty), timeout);
   53         if (timeout <= 0)
                      return;
      
   53         if (timeout == MAX_SCHEDULE_TIMEOUT)
                      timeout = 0;
      
   53         if (tty->ops->wait_until_sent)
   53                 tty->ops->wait_until_sent(tty, timeout);
      }
      EXPORT_SYMBOL(tty_wait_until_sent);
      
      
      /*
       *                Termios Helper Methods
       */
      
      static void unset_locked_termios(struct tty_struct *tty, struct ktermios *old)
      {
              struct ktermios *termios = &tty->termios;
              struct ktermios *locked  = &tty->termios_locked;
              int        i;
      
      #define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
      
              NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
              NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
              NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
              NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
   43         termios->c_line = locked->c_line ? old->c_line : termios->c_line;
              for (i = 0; i < NCCS; i++)
   43                 termios->c_cc[i] = locked->c_cc[i] ?
                              old->c_cc[i] : termios->c_cc[i];
              /* FIXME: What should we do for i/ospeed */
      }
      
      /*
       * Routine which returns the baud rate of the tty
       *
       * Note that the baud_table needs to be kept in sync with the
       * include/asm/termbits.h file.
       */
      static const speed_t baud_table[] = {
              0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
              9600, 19200, 38400, 57600, 115200, 230400, 460800,
      #ifdef __sparc__
              76800, 153600, 307200, 614400, 921600
      #else
              500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
              2500000, 3000000, 3500000, 4000000
      #endif
      };
      
      #ifndef __sparc__
      static const tcflag_t baud_bits[] = {
              B0, B50, B75, B110, B134, B150, B200, B300, B600,
              B1200, B1800, B2400, B4800, B9600, B19200, B38400,
              B57600, B115200, B230400, B460800, B500000, B576000,
              B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
              B3000000, B3500000, B4000000
      };
      #else
      static const tcflag_t baud_bits[] = {
              B0, B50, B75, B110, B134, B150, B200, B300, B600,
              B1200, B1800, B2400, B4800, B9600, B19200, B38400,
              B57600, B115200, B230400, B460800, B76800, B153600,
              B307200, B614400, B921600
      };
      #endif
      
      static int n_baud_table = ARRAY_SIZE(baud_table);
      
      /**
       *        tty_termios_baud_rate
       *        @termios: termios structure
       *
       *        Convert termios baud rate data into a speed. This should be called
       *        with the termios lock held if this termios is a terminal termios
       *        structure. May change the termios data. Device drivers can call this
       *        function but should use ->c_[io]speed directly as they are updated.
       *
       *        Locking: none
       */
      
      speed_t tty_termios_baud_rate(struct ktermios *termios)
      {
              unsigned int cbaud;
      
   92         cbaud = termios->c_cflag & CBAUD;
      
      #ifdef BOTHER
              /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
              if (cbaud == BOTHER)
   90                 return termios->c_ospeed;
      #endif
   92         if (cbaud & CBAUDEX) {
    2                 cbaud &= ~CBAUDEX;
      
   91                 if (cbaud < 1 || cbaud + 15 > n_baud_table)
                              termios->c_cflag &= ~CBAUDEX;
                      else
                              cbaud += 15;
              }
   90         return cbaud >= n_baud_table ? 0 : baud_table[cbaud];
      }
      EXPORT_SYMBOL(tty_termios_baud_rate);
      
      /**
       *        tty_termios_input_baud_rate
       *        @termios: termios structure
       *
       *        Convert termios baud rate data into a speed. This should be called
       *        with the termios lock held if this termios is a terminal termios
       *        structure. May change the termios data. Device drivers can call this
       *        function but should use ->c_[io]speed directly as they are updated.
       *
       *        Locking: none
       */
      
      speed_t tty_termios_input_baud_rate(struct ktermios *termios)
      {
      #ifdef IBSHIFT
   92         unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
      
              if (cbaud == B0)
   86                 return tty_termios_baud_rate(termios);
      
              /* Magic token for arbitrary speed via c_ispeed*/
    6         if (cbaud == BOTHER)
    4                 return termios->c_ispeed;
      
    4         if (cbaud & CBAUDEX) {
    2                 cbaud &= ~CBAUDEX;
      
    2                 if (cbaud < 1 || cbaud + 15 > n_baud_table)
                              termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
                      else
                              cbaud += 15;
              }
   92         return cbaud >= n_baud_table ? 0 : baud_table[cbaud];
      #else
              return tty_termios_baud_rate(termios);
      #endif
      }
      EXPORT_SYMBOL(tty_termios_input_baud_rate);
      
      /**
       *        tty_termios_encode_baud_rate
       *        @termios: ktermios structure holding user requested state
       *        @ispeed: input speed
       *        @ospeed: output speed
       *
       *        Encode the speeds set into the passed termios structure. This is
       *        used as a library helper for drivers so that they can report back
       *        the actual speed selected when it differs from the speed requested
       *
       *        For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
       *        we need to carefully set the bits when the user does not get the
       *        desired speed. We allow small margins and preserve as much of possible
       *        of the input intent to keep compatibility.
       *
       *        Locking: Caller should hold termios lock. This is already held
       *        when calling this function from the driver termios handler.
       *
       *        The ifdefs deal with platforms whose owners have yet to update them
       *        and will all go away once this is done.
       */
      
      void tty_termios_encode_baud_rate(struct ktermios *termios,
                                        speed_t ibaud, speed_t obaud)
      {
              int i = 0;
              int ifound = -1, ofound = -1;
              int iclose = ibaud/50, oclose = obaud/50;
              int ibinput = 0;
      
              if (obaud == 0)                        /* CD dropped                   */
                      ibaud = 0;                /* Clear ibaud to be sure */
      
              termios->c_ispeed = ibaud;
              termios->c_ospeed = obaud;
      
      #ifdef BOTHER
              /* If the user asked for a precise weird speed give a precise weird
                 answer. If they asked for a Bfoo speed they may have problems
                 digesting non-exact replies so fuzz a bit */
      
              if ((termios->c_cflag & CBAUD) == BOTHER)
                      oclose = 0;
              if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
                      iclose = 0;
              if ((termios->c_cflag >> IBSHIFT) & CBAUD)
                      ibinput = 1;        /* An input speed was specified */
      #endif
              termios->c_cflag &= ~CBAUD;
      
              /*
               *        Our goal is to find a close match to the standard baud rate
               *        returned. Walk the baud rate table and if we get a very close
               *        match then report back the speed as a POSIX Bxxxx value by
               *        preference
               */
      
              do {
                      if (obaud - oclose <= baud_table[i] &&
                          obaud + oclose >= baud_table[i]) {
                              termios->c_cflag |= baud_bits[i];
                              ofound = i;
                      }
                      if (ibaud - iclose <= baud_table[i] &&
                          ibaud + iclose >= baud_table[i]) {
                              /* For the case input == output don't set IBAUD bits
                                 if the user didn't do so */
                              if (ofound == i && !ibinput)
                                      ifound  = i;
      #ifdef IBSHIFT
                              else {
                                      ifound = i;
                                      termios->c_cflag |= (baud_bits[i] << IBSHIFT);
                              }
      #endif
                      }
              } while (++i < n_baud_table);
      
              /*
               *        If we found no match then use BOTHER if provided or warn
               *        the user their platform maintainer needs to wake up if not.
               */
      #ifdef BOTHER
              if (ofound == -1)
                      termios->c_cflag |= BOTHER;
              /* Set exact input bits only if the input and output differ or the
                 user already did */
              if (ifound == -1 && (ibaud != obaud || ibinput))
                      termios->c_cflag |= (BOTHER << IBSHIFT);
      #else
              if (ifound == -1 || ofound == -1)
                      pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating.\n");
      #endif
      }
      EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
      
      /**
       *        tty_encode_baud_rate                -        set baud rate of the tty
       *        @ibaud: input baud rate
       *        @obad: output baud rate
       *
       *        Update the current termios data for the tty with the new speed
       *        settings. The caller must hold the termios_rwsem for the tty in
       *        question.
       */
      
      void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
      {
              tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
      }
      EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
      
      /**
       *        tty_termios_copy_hw        -        copy hardware settings
       *        @new: New termios
       *        @old: Old termios
       *
       *        Propagate the hardware specific terminal setting bits from
       *        the old termios structure to the new one. This is used in cases
       *        where the hardware does not support reconfiguration or as a helper
       *        in some cases where only minimal reconfiguration is supported
       */
      
      void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
      {
              /* The bits a dumb device handles in software. Smart devices need
                 to always provide a set_termios method */
              new->c_cflag &= HUPCL | CREAD | CLOCAL;
              new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
              new->c_ispeed = old->c_ispeed;
              new->c_ospeed = old->c_ospeed;
      }
      EXPORT_SYMBOL(tty_termios_copy_hw);
      
      /**
       *        tty_termios_hw_change        -        check for setting change
       *        @a: termios
       *        @b: termios to compare
       *
       *        Check if any of the bits that affect a dumb device have changed
       *        between the two termios structures, or a speed change is needed.
       */
      
      int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
      {
              if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
                      return 1;
              if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
                      return 1;
              return 0;
      }
      EXPORT_SYMBOL(tty_termios_hw_change);
      
      /**
       *        tty_set_termios                -        update termios values
       *        @tty: tty to update
       *        @new_termios: desired new value
       *
       *        Perform updates to the termios values set on this terminal.
       *        A master pty's termios should never be set.
       *
       *        Locking: termios_rwsem
       */
      
      int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
      {
              struct ktermios old_termios;
              struct tty_ldisc *ld;
      
   43         WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY &&
                      tty->driver->subtype == PTY_TYPE_MASTER);
              /*
               *        Perform the actual termios internal changes under lock.
               */
      
      
              /* FIXME: we need to decide on some locking/ordering semantics
                 for the set_termios notification eventually */
   43         down_write(&tty->termios_rwsem);
              old_termios = tty->termios;
              tty->termios = *new_termios;
   43         unset_locked_termios(tty, &old_termios);
      
   42         if (tty->ops->set_termios)
   42                 tty->ops->set_termios(tty, &old_termios);
              else
                      tty_termios_copy_hw(&tty->termios, &old_termios);
      
   42         ld = tty_ldisc_ref(tty);
              if (ld != NULL) {
   41                 if (ld->ops->set_termios)
   41                         ld->ops->set_termios(tty, &old_termios);
   41                 tty_ldisc_deref(ld);
              }
   42         up_write(&tty->termios_rwsem);
              return 0;
      }
      EXPORT_SYMBOL_GPL(tty_set_termios);
      
      /**
       *        set_termios                -        set termios values for a tty
       *        @tty: terminal device
       *        @arg: user data
       *        @opt: option information
       *
       *        Helper function to prepare termios data and run necessary other
       *        functions before using tty_set_termios to do the actual changes.
       *
       *        Locking:
       *                Called functions take ldisc and termios_rwsem locks
       */
      
   52 static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
      {
              struct ktermios tmp_termios;
              struct tty_ldisc *ld;
   52         int retval = tty_check_change(tty);
      
   44         if (retval)
                      return retval;
      
   52         down_read(&tty->termios_rwsem);
              tmp_termios = tty->termios;
              up_read(&tty->termios_rwsem);
      
              if (opt & TERMIOS_TERMIO) {
   18                 if (user_termio_to_kernel_termios(&tmp_termios,
                                                      (struct termio __user *)arg))
                              return -EFAULT;
      #ifdef TCGETS2
   34         } else if (opt & TERMIOS_OLD) {
   29                 if (user_termios_to_kernel_termios_1(&tmp_termios,
                                                      (struct termios __user *)arg))
                              return -EFAULT;
              } else {
    5                 if (user_termios_to_kernel_termios(&tmp_termios,
                                                      (struct termios2 __user *)arg))
                              return -EFAULT;
              }
      #else
              } else if (user_termios_to_kernel_termios(&tmp_termios,
                                              (struct termios __user *)arg))
                      return -EFAULT;
      #endif
      
              /* If old style Bfoo values are used then load c_ispeed/c_ospeed
               * with the real speed so its unconditionally usable */
   48         tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
              tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
      
              ld = tty_ldisc_ref(tty);
      
              if (ld != NULL) {
   43                 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
   23                         ld->ops->flush_buffer(tty);
   42                 tty_ldisc_deref(ld);
              }
      
   43         if (opt & TERMIOS_WAIT) {
   26                 tty_wait_until_sent(tty, 0);
                      if (signal_pending(current))
                              return -ERESTARTSYS;
              }
      
   43         tty_set_termios(tty, &tmp_termios);
      
              /* FIXME: Arguably if tmp_termios == tty->termios AND the
                 actual requested termios was not tmp_termios then we may
                 want to return an error as no user requested change has
                 succeeded */
   44         return 0;
      }
      
      static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
      {
    8         down_read(&tty->termios_rwsem);
              *kterm = tty->termios;
              up_read(&tty->termios_rwsem);
      }
      
      static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
      {
    5         down_read(&tty->termios_rwsem);
              *kterm = tty->termios_locked;
              up_read(&tty->termios_rwsem);
      }
      
      static int get_termio(struct tty_struct *tty, struct termio __user *termio)
      {
              struct ktermios kterm;
    5         copy_termios(tty, &kterm);
    5         if (kernel_termios_to_user_termio(termio, &kterm))
                      return -EFAULT;
    5         return 0;
      }
      
      
      #ifdef TCGETX
      
      /**
       *        set_termiox        -        set termiox fields if possible
       *        @tty: terminal
       *        @arg: termiox structure from user
       *        @opt: option flags for ioctl type
       *
       *        Implement the device calling points for the SYS5 termiox ioctl
       *        interface in Linux
       */
      
      static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
      {
              struct termiox tnew;
              struct tty_ldisc *ld;
      
    3         if (tty->termiox == NULL)
                      return -EINVAL;
              if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
                      return -EFAULT;
      
              ld = tty_ldisc_ref(tty);
              if (ld != NULL) {
                      if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
                              ld->ops->flush_buffer(tty);
                      tty_ldisc_deref(ld);
              }
              if (opt & TERMIOS_WAIT) {
                      tty_wait_until_sent(tty, 0);
                      if (signal_pending(current))
                              return -ERESTARTSYS;
              }
      
              down_write(&tty->termios_rwsem);
              if (tty->ops->set_termiox)
                      tty->ops->set_termiox(tty, &tnew);
              up_write(&tty->termios_rwsem);
    3         return 0;
      }
      
      #endif
      
      
      #ifdef TIOCGETP
      /*
       * These are deprecated, but there is limited support..
       *
       * The "sg_flags" translation is a joke..
       */
      static int get_sgflags(struct tty_struct *tty)
      {
              int flags = 0;
      
              if (!L_ICANON(tty)) {
                      if (L_ISIG(tty))
                              flags |= 0x02;                /* cbreak */
                      else
                              flags |= 0x20;                /* raw */
              }
              if (L_ECHO(tty))
                      flags |= 0x08;                        /* echo */
              if (O_OPOST(tty))
                      if (O_ONLCR(tty))
                              flags |= 0x10;                /* crmod */
              return flags;
      }
      
      static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
      {
              struct sgttyb tmp;
      
              down_read(&tty->termios_rwsem);
              tmp.sg_ispeed = tty->termios.c_ispeed;
              tmp.sg_ospeed = tty->termios.c_ospeed;
              tmp.sg_erase = tty->termios.c_cc[VERASE];
              tmp.sg_kill = tty->termios.c_cc[VKILL];
              tmp.sg_flags = get_sgflags(tty);
              up_read(&tty->termios_rwsem);
      
              return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
      }
      
      static void set_sgflags(struct ktermios *termios, int flags)
      {
              termios->c_iflag = ICRNL | IXON;
              termios->c_oflag = 0;
              termios->c_lflag = ISIG | ICANON;
              if (flags & 0x02) {        /* cbreak */
                      termios->c_iflag = 0;
                      termios->c_lflag &= ~ICANON;
              }
              if (flags & 0x08) {                /* echo */
                      termios->c_lflag |= ECHO | ECHOE | ECHOK |
                                          ECHOCTL | ECHOKE | IEXTEN;
              }
              if (flags & 0x10) {                /* crmod */
                      termios->c_oflag |= OPOST | ONLCR;
              }
              if (flags & 0x20) {        /* raw */
                      termios->c_iflag = 0;
                      termios->c_lflag &= ~(ISIG | ICANON);
              }
              if (!(termios->c_lflag & ICANON)) {
                      termios->c_cc[VMIN] = 1;
                      termios->c_cc[VTIME] = 0;
              }
      }
      
      /**
       *        set_sgttyb                -        set legacy terminal values
       *        @tty: tty structure
       *        @sgttyb: pointer to old style terminal structure
       *
       *        Updates a terminal from the legacy BSD style terminal information
       *        structure.
       *
       *        Locking: termios_rwsem
       */
      
      static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
      {
              int retval;
              struct sgttyb tmp;
              struct ktermios termios;
      
              retval = tty_check_change(tty);
              if (retval)
                      return retval;
      
              if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
                      return -EFAULT;
      
              down_write(&tty->termios_rwsem);
              termios = tty->termios;
              termios.c_cc[VERASE] = tmp.sg_erase;
              termios.c_cc[VKILL] = tmp.sg_kill;
              set_sgflags(&termios, tmp.sg_flags);
              /* Try and encode into Bfoo format */
      #ifdef BOTHER
              tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
                                                      termios.c_ospeed);
      #endif
              up_write(&tty->termios_rwsem);
              tty_set_termios(tty, &termios);
              return 0;
      }
      #endif
      
      #ifdef TIOCGETC
      static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
      {
              struct tchars tmp;
      
              down_read(&tty->termios_rwsem);
              tmp.t_intrc = tty->termios.c_cc[VINTR];
              tmp.t_quitc = tty->termios.c_cc[VQUIT];
              tmp.t_startc = tty->termios.c_cc[VSTART];
              tmp.t_stopc = tty->termios.c_cc[VSTOP];
              tmp.t_eofc = tty->termios.c_cc[VEOF];
              tmp.t_brkc = tty->termios.c_cc[VEOL2];        /* what is brkc anyway? */
              up_read(&tty->termios_rwsem);
              return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
      }
      
      static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
      {
              struct tchars tmp;
      
              if (copy_from_user(&tmp, tchars, sizeof(tmp)))
                      return -EFAULT;
              down_write(&tty->termios_rwsem);
              tty->termios.c_cc[VINTR] = tmp.t_intrc;
              tty->termios.c_cc[VQUIT] = tmp.t_quitc;
              tty->termios.c_cc[VSTART] = tmp.t_startc;
              tty->termios.c_cc[VSTOP] = tmp.t_stopc;
              tty->termios.c_cc[VEOF] = tmp.t_eofc;
              tty->termios.c_cc[VEOL2] = tmp.t_brkc;        /* what is brkc anyway? */
              up_write(&tty->termios_rwsem);
              return 0;
      }
      #endif
      
      #ifdef TIOCGLTC
      static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
      {
              struct ltchars tmp;
      
              down_read(&tty->termios_rwsem);
              tmp.t_suspc = tty->termios.c_cc[VSUSP];
              /* what is dsuspc anyway? */
              tmp.t_dsuspc = tty->termios.c_cc[VSUSP];
              tmp.t_rprntc = tty->termios.c_cc[VREPRINT];
              /* what is flushc anyway? */
              tmp.t_flushc = tty->termios.c_cc[VEOL2];
              tmp.t_werasc = tty->termios.c_cc[VWERASE];
              tmp.t_lnextc = tty->termios.c_cc[VLNEXT];
              up_read(&tty->termios_rwsem);
              return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
      }
      
      static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
      {
              struct ltchars tmp;
      
              if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
                      return -EFAULT;
      
              down_write(&tty->termios_rwsem);
              tty->termios.c_cc[VSUSP] = tmp.t_suspc;
              /* what is dsuspc anyway? */
              tty->termios.c_cc[VEOL2] = tmp.t_dsuspc;
              tty->termios.c_cc[VREPRINT] = tmp.t_rprntc;
              /* what is flushc anyway? */
              tty->termios.c_cc[VEOL2] = tmp.t_flushc;
              tty->termios.c_cc[VWERASE] = tmp.t_werasc;
              tty->termios.c_cc[VLNEXT] = tmp.t_lnextc;
              up_write(&tty->termios_rwsem);
              return 0;
      }
      #endif
      
      /**
       *        tty_change_softcar        -        carrier change ioctl helper
       *        @tty: tty to update
       *        @arg: enable/disable CLOCAL
       *
       *        Perform a change to the CLOCAL state and call into the driver
       *        layer to make it visible. All done with the termios rwsem
       */
      
      static int tty_change_softcar(struct tty_struct *tty, int arg)
      {
              int ret = 0;
    3         int bit = arg ? CLOCAL : 0;
              struct ktermios old;
      
    3         down_write(&tty->termios_rwsem);
              old = tty->termios;
              tty->termios.c_cflag &= ~CLOCAL;
              tty->termios.c_cflag |= bit;
              if (tty->ops->set_termios)
    3                 tty->ops->set_termios(tty, &old);
    3         if (C_CLOCAL(tty) != bit)
                      ret = -EINVAL;
    3         up_write(&tty->termios_rwsem);
              return ret;
      }
      
      /**
       *        tty_mode_ioctl                -        mode related ioctls
       *        @tty: tty for the ioctl
       *        @file: file pointer for the tty
       *        @cmd: command
       *        @arg: ioctl argument
       *
       *        Perform non line discipline specific mode control ioctls. This
       *        is designed to be called by line disciplines to ensure they provide
       *        consistent mode setting.
       */
      
      int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
                              unsigned int cmd, unsigned long arg)
      {
              struct tty_struct *real_tty;
   78         void __user *p = (void __user *)arg;
              int ret = 0;
              struct ktermios kterm;
      
              BUG_ON(file == NULL);
      
   78         if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
                  tty->driver->subtype == PTY_TYPE_MASTER)
   63                 real_tty = tty->link;
              else
                      real_tty = tty;
      
   78         switch (cmd) {
      #ifdef TIOCGETP
              case TIOCGETP:
                      return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
              case TIOCSETP:
              case TIOCSETN:
                      return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
      #endif
      #ifdef TIOCGETC
              case TIOCGETC:
                      return get_tchars(real_tty, p);
              case TIOCSETC:
                      return set_tchars(real_tty, p);
      #endif
      #ifdef TIOCGLTC
              case TIOCGLTC:
                      return get_ltchars(real_tty, p);
              case TIOCSLTC:
                      return set_ltchars(real_tty, p);
      #endif
              case TCSETSF:
   18                 return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
              case TCSETSW:
    4                 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
              case TCSETS:
    7                 return set_termios(real_tty, p, TERMIOS_OLD);
      #ifndef TCGETS2
              case TCGETS:
                      copy_termios(real_tty, &kterm);
                      if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
                              ret = -EFAULT;
                      return ret;
      #else
              case TCGETS:
    1                 copy_termios(real_tty, &kterm);
                      if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
                              ret = -EFAULT;
                      return ret;
              case TCGETS2:
    1                 copy_termios(real_tty, &kterm);
                      if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
                              ret = -EFAULT;
                      return ret;
              case TCSETSF2:
                      return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
              case TCSETSW2:
                      return set_termios(real_tty, p, TERMIOS_WAIT);
              case TCSETS2:
    5                 return set_termios(real_tty, p, 0);
      #endif
              case TCGETA:
    5                 return get_termio(real_tty, p);
              case TCSETAF:
    7                 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
              case TCSETAW:
    1                 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
              case TCSETA:
   13                 return set_termios(real_tty, p, TERMIOS_TERMIO);
      #ifndef TCGETS2
              case TIOCGLCKTRMIOS:
                      copy_termios_locked(real_tty, &kterm);
                      if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
                              ret = -EFAULT;
                      return ret;
              case TIOCSLCKTRMIOS:
                      if (!capable(CAP_SYS_ADMIN))
                              return -EPERM;
                      copy_termios_locked(real_tty, &kterm);
                      if (user_termios_to_kernel_termios(&kterm,
                                                     (struct termios __user *) arg))
                              return -EFAULT;
                      down_write(&real_tty->termios_rwsem);
                      real_tty->termios_locked = kterm;
                      up_write(&real_tty->termios_rwsem);
                      return 0;
      #else
              case TIOCGLCKTRMIOS:
    2                 copy_termios_locked(real_tty, &kterm);
                      if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
                              ret = -EFAULT;
                      return ret;
              case TIOCSLCKTRMIOS:
    4                 if (!capable(CAP_SYS_ADMIN))
                              return -EPERM;
    3                 copy_termios_locked(real_tty, &kterm);
                      if (user_termios_to_kernel_termios_1(&kterm,
                                                     (struct termios __user *) arg))
                              return -EFAULT;
    2                 down_write(&real_tty->termios_rwsem);
                      real_tty->termios_locked = kterm;
                      up_write(&real_tty->termios_rwsem);
                      return ret;
      #endif
      #ifdef TCGETX
              case TCGETX: {
                      struct termiox ktermx;
    1                 if (real_tty->termiox == NULL)
                              return -EINVAL;
                      down_read(&real_tty->termios_rwsem);
                      memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox));
                      up_read(&real_tty->termios_rwsem);
                      if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
    1                         ret = -EFAULT;
                      return ret;
              }
              case TCSETX:
    1                 return set_termiox(real_tty, p, 0);
              case TCSETXW:
    1                 return set_termiox(real_tty, p, TERMIOS_WAIT);
              case TCSETXF:
    1                 return set_termiox(real_tty, p, TERMIOS_FLUSH);
      #endif                
              case TIOCGSOFTCAR:
    1                 copy_termios(real_tty, &kterm);
                      ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
                                                      (int __user *)arg);
                      return ret;
              case TIOCSSOFTCAR:
    4                 if (get_user(arg, (unsigned int __user *) arg))
                              return -EFAULT;
    3                 return tty_change_softcar(real_tty, arg);
              default:
                      return -ENOIOCTLCMD;
              }
      }
      EXPORT_SYMBOL_GPL(tty_mode_ioctl);
      
      
      /* Caller guarantees ldisc reference is held */
    4 static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
      {
    9         struct tty_ldisc *ld = tty->ldisc;
      
    8         switch (arg) {
              case TCIFLUSH:
    4                 if (ld && ld->ops->flush_buffer) {
    4                         ld->ops->flush_buffer(tty);
                              tty_unthrottle(tty);
                      }
                      break;
              case TCIOFLUSH:
    3                 if (ld && ld->ops->flush_buffer) {
    3                         ld->ops->flush_buffer(tty);
                              tty_unthrottle(tty);
                      }
                      /* fall through */
              case TCOFLUSH:
    4                 tty_driver_flush_buffer(tty);
                      break;
              default:
                      return -EINVAL;
              }
              return 0;
      }
      
      int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
      {
              struct tty_ldisc *ld;
              int retval = tty_check_change(tty);
              if (retval)
                      return retval;
      
              ld = tty_ldisc_ref_wait(tty);
              retval = __tty_perform_flush(tty, arg);
              if (ld)
                      tty_ldisc_deref(ld);
              return retval;
      }
      EXPORT_SYMBOL_GPL(tty_perform_flush);
      
   16 int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
                             unsigned int cmd, unsigned long arg)
      {
              int retval;
      
  103         switch (cmd) {
              case TCXONC:
   16                 retval = tty_check_change(tty);
                      if (retval)
                              return retval;
   16                 switch (arg) {
                      case TCOOFF:
    6                         spin_lock_irq(&tty->flow_lock);
                              if (!tty->flow_stopped) {
    5                                 tty->flow_stopped = 1;
                                      __stop_tty(tty);
                              }
                              spin_unlock_irq(&tty->flow_lock);
                              break;
                      case TCOON:
    5                         spin_lock_irq(&tty->flow_lock);
                              if (tty->flow_stopped) {
    3                                 tty->flow_stopped = 0;
                                      __start_tty(tty);
                              }
   10                         spin_unlock_irq(&tty->flow_lock);
                              break;
                      case TCIOFF:
    3                         if (STOP_CHAR(tty) != __DISABLED_CHAR)
                                      retval = tty_send_xchar(tty, STOP_CHAR(tty));
                              break;
                      case TCION:
    4                         if (START_CHAR(tty) != __DISABLED_CHAR)
    7                                 retval = tty_send_xchar(tty, START_CHAR(tty));
                              break;
                      default:
                              return -EINVAL;
                      }
                      return retval;
              case TCFLSH:
    9                 retval = tty_check_change(tty);
                      if (retval)
                              return retval;
    9                 return __tty_perform_flush(tty, arg);
              default:
                      /* Try the mode commands */
  102                 return tty_mode_ioctl(tty, file, cmd, arg);
              }
      }
      EXPORT_SYMBOL(n_tty_ioctl_helper);
      
      #ifdef CONFIG_COMPAT
      long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file,
                                              unsigned int cmd, unsigned long arg)
    2 {
              switch (cmd) {
              case TIOCGLCKTRMIOS:
              case TIOCSLCKTRMIOS:
    2                 return tty_mode_ioctl(tty, file, cmd, (unsigned long) compat_ptr(arg));
              default:
                      return -ENOIOCTLCMD;
              }
      }
      EXPORT_SYMBOL(n_tty_compat_ioctl_helper);
      #endif
      
      /*
        FUSE: Filesystem in Userspace
        Copyright (C) 2001-2008  Miklos Szeredi <miklos@szeredi.hu>
      
        This program can be distributed under the terms of the GNU GPL.
        See the file COPYING.
      */
      
      #include "fuse_i.h"
      
      #include <linux/init.h>
      #include <linux/module.h>
      
      #define FUSE_CTL_SUPER_MAGIC 0x65735543
      
      /*
       * This is non-NULL when the single instance of the control filesystem
       * exists.  Protected by fuse_mutex
       */
      static struct super_block *fuse_control_sb;
      
      static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file)
      {
              struct fuse_conn *fc;
              mutex_lock(&fuse_mutex);
              fc = file_inode(file)->i_private;
              if (fc)
                      fc = fuse_conn_get(fc);
              mutex_unlock(&fuse_mutex);
              return fc;
      }
      
      static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
                                           size_t count, loff_t *ppos)
      {
              struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
              if (fc) {
                      fuse_abort_conn(fc);
                      fuse_conn_put(fc);
              }
              return count;
      }
      
      static ssize_t fuse_conn_waiting_read(struct file *file, char __user *buf,
                                            size_t len, loff_t *ppos)
      {
              char tmp[32];
              size_t size;
      
              if (!*ppos) {
                      long value;
                      struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
                      if (!fc)
                              return 0;
      
                      value = atomic_read(&fc->num_waiting);
                      file->private_data = (void *)value;
                      fuse_conn_put(fc);
              }
              size = sprintf(tmp, "%ld\n", (long)file->private_data);
              return simple_read_from_buffer(buf, len, ppos, tmp, size);
      }
      
      static ssize_t fuse_conn_limit_read(struct file *file, char __user *buf,
                                          size_t len, loff_t *ppos, unsigned val)
      {
              char tmp[32];
              size_t size = sprintf(tmp, "%u\n", val);
      
              return simple_read_from_buffer(buf, len, ppos, tmp, size);
      }
      
      static ssize_t fuse_conn_limit_write(struct file *file, const char __user *buf,
                                           size_t count, loff_t *ppos, unsigned *val,
                                           unsigned global_limit)
      {
              unsigned long t;
              unsigned limit = (1 << 16) - 1;
              int err;
      
              if (*ppos)
                      return -EINVAL;
      
              err = kstrtoul_from_user(buf, count, 0, &t);
              if (err)
                      return err;
      
              if (!capable(CAP_SYS_ADMIN))
                      limit = min(limit, global_limit);
      
              if (t > limit)
                      return -EINVAL;
      
              *val = t;
      
              return count;
      }
      
      static ssize_t fuse_conn_max_background_read(struct file *file,
                                                   char __user *buf, size_t len,
                                                   loff_t *ppos)
      {
              struct fuse_conn *fc;
              unsigned val;
      
              fc = fuse_ctl_file_conn_get(file);
              if (!fc)
                      return 0;
      
              val = READ_ONCE(fc->max_background);
              fuse_conn_put(fc);
      
              return fuse_conn_limit_read(file, buf, len, ppos, val);
      }
      
      static ssize_t fuse_conn_max_background_write(struct file *file,
                                                    const char __user *buf,
                                                    size_t count, loff_t *ppos)
      {
              unsigned uninitialized_var(val);
              ssize_t ret;
      
              ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
                                          max_user_bgreq);
              if (ret > 0) {
                      struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
                      if (fc) {
                              fc->max_background = val;
                              fuse_conn_put(fc);
                      }
              }
      
              return ret;
      }
      
      static ssize_t fuse_conn_congestion_threshold_read(struct file *file,
                                                         char __user *buf, size_t len,
                                                         loff_t *ppos)
      {
              struct fuse_conn *fc;
              unsigned val;
      
              fc = fuse_ctl_file_conn_get(file);
              if (!fc)
                      return 0;
      
              val = READ_ONCE(fc->congestion_threshold);
              fuse_conn_put(fc);
      
              return fuse_conn_limit_read(file, buf, len, ppos, val);
      }
      
      static ssize_t fuse_conn_congestion_threshold_write(struct file *file,
                                                          const char __user *buf,
                                                          size_t count, loff_t *ppos)
      {
              unsigned uninitialized_var(val);
              ssize_t ret;
      
              ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
                                          max_user_congthresh);
              if (ret > 0) {
                      struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
                      if (fc) {
                              fc->congestion_threshold = val;
                              fuse_conn_put(fc);
                      }
              }
      
              return ret;
      }
      
      static const struct file_operations fuse_ctl_abort_ops = {
              .open = nonseekable_open,
              .write = fuse_conn_abort_write,
              .llseek = no_llseek,
      };
      
      static const struct file_operations fuse_ctl_waiting_ops = {
              .open = nonseekable_open,
              .read = fuse_conn_waiting_read,
              .llseek = no_llseek,
      };
      
      static const struct file_operations fuse_conn_max_background_ops = {
              .open = nonseekable_open,
              .read = fuse_conn_max_background_read,
              .write = fuse_conn_max_background_write,
              .llseek = no_llseek,
      };
      
      static const struct file_operations fuse_conn_congestion_threshold_ops = {
              .open = nonseekable_open,
              .read = fuse_conn_congestion_threshold_read,
              .write = fuse_conn_congestion_threshold_write,
              .llseek = no_llseek,
      };
      
      static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
                                                struct fuse_conn *fc,
                                                const char *name,
                                                int mode, int nlink,
                                                const struct inode_operations *iop,
                                                const struct file_operations *fop)
      {
              struct dentry *dentry;
              struct inode *inode;
      
  100         BUG_ON(fc->ctl_ndents >= FUSE_CTL_NUM_DENTRIES);
  100         dentry = d_alloc_name(parent, name);
              if (!dentry)
                      return NULL;
      
  100         inode = new_inode(fuse_control_sb);
              if (!inode) {
                      dput(dentry);
                      return NULL;
              }
      
  100         inode->i_ino = get_next_ino();
              inode->i_mode = mode;
              inode->i_uid = fc->user_id;
              inode->i_gid = fc->group_id;
              inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
              /* setting ->i_op to NULL is not allowed */
              if (iop)
  100                 inode->i_op = iop;
  100         inode->i_fop = fop;
              set_nlink(inode, nlink);
              inode->i_private = fc;
              d_add(dentry, inode);
      
              fc->ctl_dentry[fc->ctl_ndents++] = dentry;
      
  100         return dentry;
      }
      
      /*
       * Add a connection to the control filesystem (if it exists).  Caller
       * must hold fuse_mutex
       */
      int fuse_ctl_add_conn(struct fuse_conn *fc)
      {
              struct dentry *parent;
              char name[32];
      
  100         if (!fuse_control_sb)
  100                 return 0;
      
  100         parent = fuse_control_sb->s_root;
              inc_nlink(d_inode(parent));
              sprintf(name, "%u", fc->dev);
              parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
                                           &simple_dir_inode_operations,
                                           &simple_dir_operations);
              if (!parent)
                      goto err;
      
  100         if (!fuse_ctl_add_dentry(parent, fc, "waiting", S_IFREG | 0400, 1,
                                       NULL, &fuse_ctl_waiting_ops) ||
  100             !fuse_ctl_add_dentry(parent, fc, "abort", S_IFREG | 0200, 1,
                                       NULL, &fuse_ctl_abort_ops) ||
  100             !fuse_ctl_add_dentry(parent, fc, "max_background", S_IFREG | 0600,
                                       1, NULL, &fuse_conn_max_background_ops) ||
  100             !fuse_ctl_add_dentry(parent, fc, "congestion_threshold",
                                       S_IFREG | 0600, 1, NULL,
                                       &fuse_conn_congestion_threshold_ops))
                      goto err;
      
              return 0;
      
       err:
              fuse_ctl_remove_conn(fc);
              return -ENOMEM;
      }
      
      /*
       * Remove a connection from the control filesystem (if it exists).
       * Caller must hold fuse_mutex
       */
      void fuse_ctl_remove_conn(struct fuse_conn *fc)
      {
              int i;
      
   49         if (!fuse_control_sb)
                      return;
      
   49         for (i = fc->ctl_ndents - 1; i >= 0; i--) {
   49                 struct dentry *dentry = fc->ctl_dentry[i];
                      d_inode(dentry)->i_private = NULL;
                      if (!i) {
                              /* Get rid of submounts: */
   49                         d_invalidate(dentry);
                      }
   49                 dput(dentry);
              }
   49         drop_nlink(d_inode(fuse_control_sb->s_root));
      }
      
      static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent)
      {
              struct tree_descr empty_descr = {""};
              struct fuse_conn *fc;
              int err;
      
              err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
              if (err)
                      return err;
      
              mutex_lock(&fuse_mutex);
              BUG_ON(fuse_control_sb);
              fuse_control_sb = sb;
              list_for_each_entry(fc, &fuse_conn_list, entry) {
                      err = fuse_ctl_add_conn(fc);
                      if (err) {
                              fuse_control_sb = NULL;
                              mutex_unlock(&fuse_mutex);
                              return err;
                      }
              }
              mutex_unlock(&fuse_mutex);
      
              return 0;
      }
      
      static struct dentry *fuse_ctl_mount(struct file_system_type *fs_type,
                              int flags, const char *dev_name, void *raw_data)
      {
    1         return mount_single(fs_type, flags, raw_data, fuse_ctl_fill_super);
      }
      
      static void fuse_ctl_kill_sb(struct super_block *sb)
      {
              struct fuse_conn *fc;
      
              mutex_lock(&fuse_mutex);
              fuse_control_sb = NULL;
              list_for_each_entry(fc, &fuse_conn_list, entry)
                      fc->ctl_ndents = 0;
              mutex_unlock(&fuse_mutex);
      
              kill_litter_super(sb);
      }
      
      static struct file_system_type fuse_ctl_fs_type = {
              .owner                = THIS_MODULE,
              .name                = "fusectl",
              .mount                = fuse_ctl_mount,
              .kill_sb        = fuse_ctl_kill_sb,
      };
      MODULE_ALIAS_FS("fusectl");
      
      int __init fuse_ctl_init(void)
      {
              return register_filesystem(&fuse_ctl_fs_type);
      }
      
      void __exit fuse_ctl_cleanup(void)
      {
              unregister_filesystem(&fuse_ctl_fs_type);
      }
      /*
       * INET                An implementation of the TCP/IP protocol suite for the LINUX
       *                operating system.  INET is implemented using the  BSD Socket
       *                interface as the means of communication with the user level.
       *
       *                Global definitions for the Ethernet IEEE 802.3 interface.
       *
       * Version:        @(#)if_ether.h        1.0.1a        02/08/94
       *
       * Author:        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
       *                Donald Becker, <becker@super.org>
       *                Alan Cox, <alan@lxorguk.ukuu.org.uk>
       *                Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
       *
       *                This program is free software; you can redistribute it and/or
       *                modify it under the terms of the GNU General Public License
       *                as published by the Free Software Foundation; either version
       *                2 of the License, or (at your option) any later version.
       */
      #ifndef _LINUX_IF_ETHER_H
      #define _LINUX_IF_ETHER_H
      
      #include <linux/skbuff.h>
      #include <uapi/linux/if_ether.h>
      
      static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
      {
  216         return (struct ethhdr *)skb_mac_header(skb);
      }
      
      static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb)
      {
              return (struct ethhdr *)skb_inner_mac_header(skb);
      }
      
      int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr);
      
      extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len);
      
      #endif        /* _LINUX_IF_ETHER_H */
      /* netfilter.c: look after the filters for various protocols.
       * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
       *
       * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
       * way.
       *
       * Rusty Russell (C)2000 -- This code is GPL.
       * Patrick McHardy (c) 2006-2012
       */
      #include <linux/kernel.h>
      #include <linux/netfilter.h>
      #include <net/protocol.h>
      #include <linux/init.h>
      #include <linux/skbuff.h>
      #include <linux/wait.h>
      #include <linux/module.h>
      #include <linux/interrupt.h>
      #include <linux/if.h>
      #include <linux/netdevice.h>
      #include <linux/netfilter_ipv6.h>
      #include <linux/inetdevice.h>
      #include <linux/proc_fs.h>
      #include <linux/mutex.h>
      #include <linux/slab.h>
      #include <linux/rcupdate.h>
      #include <net/net_namespace.h>
      #include <net/sock.h>
      
      #include "nf_internals.h"
      
      static DEFINE_MUTEX(afinfo_mutex);
      
      const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
      EXPORT_SYMBOL(nf_afinfo);
      const struct nf_ipv6_ops __rcu *nf_ipv6_ops __read_mostly;
      EXPORT_SYMBOL_GPL(nf_ipv6_ops);
      
      DEFINE_PER_CPU(bool, nf_skb_duplicated);
      EXPORT_SYMBOL_GPL(nf_skb_duplicated);
      
      int nf_register_afinfo(const struct nf_afinfo *afinfo)
      {
              mutex_lock(&afinfo_mutex);
              RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo);
              mutex_unlock(&afinfo_mutex);
              return 0;
      }
      EXPORT_SYMBOL_GPL(nf_register_afinfo);
      
      void nf_unregister_afinfo(const struct nf_afinfo *afinfo)
      {
              mutex_lock(&afinfo_mutex);
              RCU_INIT_POINTER(nf_afinfo[afinfo->family], NULL);
              mutex_unlock(&afinfo_mutex);
              synchronize_rcu();
      }
      EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
      
      #ifdef HAVE_JUMP_LABEL
      struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
      EXPORT_SYMBOL(nf_hooks_needed);
      #endif
      
      static DEFINE_MUTEX(nf_hook_mutex);
      #define nf_entry_dereference(e) \
              rcu_dereference_protected(e, lockdep_is_held(&nf_hook_mutex))
      
      static struct nf_hook_entry __rcu **nf_hook_entry_head(struct net *net, const struct nf_hook_ops *reg)
      {
              if (reg->pf != NFPROTO_NETDEV)
  115                 return net->nf.hooks[reg->pf]+reg->hooknum;
      
      #ifdef CONFIG_NETFILTER_INGRESS
              if (reg->hooknum == NF_NETDEV_INGRESS) {
                      if (reg->dev && dev_net(reg->dev) == net)
                              return &reg->dev->nf_hooks_ingress;
              }
      #endif
              return NULL;
      }
      
      int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)
      {
              struct nf_hook_entry __rcu **pp;
              struct nf_hook_entry *entry, *p;
      
  115         if (reg->pf == NFPROTO_NETDEV) {
      #ifndef CONFIG_NETFILTER_INGRESS
                      if (reg->hooknum == NF_NETDEV_INGRESS)
                              return -EOPNOTSUPP;
      #endif
                      if (reg->hooknum != NF_NETDEV_INGRESS ||
                          !reg->dev || dev_net(reg->dev) != net)
                              return -EINVAL;
              }
      
  115         pp = nf_hook_entry_head(net, reg);
  115         if (!pp)
                      return -EINVAL;
      
  115         entry = kmalloc(sizeof(*entry), GFP_KERNEL);
              if (!entry)
                      return -ENOMEM;
      
  115         entry->orig_ops        = reg;
              entry->ops        = *reg;
              entry->next        = NULL;
      
              mutex_lock(&nf_hook_mutex);
      
              /* Find the spot in the list */
  115         while ((p = nf_entry_dereference(*pp)) != NULL) {
  115                 if (reg->priority < p->orig_ops->priority)
                              break;
  115                 pp = &p->next;
              }
  115         rcu_assign_pointer(entry->next, p);
              rcu_assign_pointer(*pp, entry);
      
              mutex_unlock(&nf_hook_mutex);
      #ifdef CONFIG_NETFILTER_INGRESS
  115         if (reg->pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS)
                      net_inc_ingress_queue();
      #endif
      #ifdef HAVE_JUMP_LABEL
              static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]);
      #endif
              return 0;
  115 }
      EXPORT_SYMBOL(nf_register_net_hook);
      
      void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)
      {
              struct nf_hook_entry __rcu **pp;
              struct nf_hook_entry *p;
      
              pp = nf_hook_entry_head(net, reg);
              if (WARN_ON_ONCE(!pp))
                      return;
      
              mutex_lock(&nf_hook_mutex);
              while ((p = nf_entry_dereference(*pp)) != NULL) {
                      if (p->orig_ops == reg) {
                              rcu_assign_pointer(*pp, p->next);
                              break;
                      }
                      pp = &p->next;
              }
              mutex_unlock(&nf_hook_mutex);
              if (!p) {
                      WARN(1, "nf_unregister_net_hook: hook not found!\n");
                      return;
              }
      #ifdef CONFIG_NETFILTER_INGRESS
              if (reg->pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS)
                      net_dec_ingress_queue();
      #endif
      #ifdef HAVE_JUMP_LABEL
              static_key_slow_dec(&nf_hooks_needed[reg->pf][reg->hooknum]);
      #endif
              synchronize_net();
              nf_queue_nf_hook_drop(net, p);
              /* other cpu might still process nfqueue verdict that used reg */
              synchronize_net();
              kfree(p);
      }
      EXPORT_SYMBOL(nf_unregister_net_hook);
      
      int nf_register_net_hooks(struct net *net, const struct nf_hook_ops *reg,
                                unsigned int n)
      {
              unsigned int i;
              int err = 0;
      
   11         for (i = 0; i < n; i++) {
   11                 err = nf_register_net_hook(net, &reg[i]);
                      if (err)
                              goto err;
              }
   11         return err;
      
      err:
              if (i > 0)
                      nf_unregister_net_hooks(net, reg, i);
              return err;
      }
      EXPORT_SYMBOL(nf_register_net_hooks);
      
      void nf_unregister_net_hooks(struct net *net, const struct nf_hook_ops *reg,
                                   unsigned int n)
      {
              while (n-- > 0)
                      nf_unregister_net_hook(net, &reg[n]);
      }
      EXPORT_SYMBOL(nf_unregister_net_hooks);
      
      static LIST_HEAD(nf_hook_list);
      
      static int _nf_register_hook(struct nf_hook_ops *reg)
      {
              struct net *net, *last;
              int ret;
      
              for_each_net(net) {
                      ret = nf_register_net_hook(net, reg);
                      if (ret && ret != -ENOENT)
                              goto rollback;
              }
              list_add_tail(&reg->list, &nf_hook_list);
      
              return 0;
      rollback:
              last = net;
              for_each_net(net) {
                      if (net == last)
                              break;
                      nf_unregister_net_hook(net, reg);
              }
              return ret;
      }
      
      int nf_register_hook(struct nf_hook_ops *reg)
      {
              int ret;
      
              rtnl_lock();
              ret = _nf_register_hook(reg);
              rtnl_unlock();
      
              return ret;
      }
      EXPORT_SYMBOL(nf_register_hook);
      
      static void _nf_unregister_hook(struct nf_hook_ops *reg)
      {
              struct net *net;
      
              list_del(&reg->list);
              for_each_net(net)
                      nf_unregister_net_hook(net, reg);
      }
      
      void nf_unregister_hook(struct nf_hook_ops *reg)
      {
              rtnl_lock();
              _nf_unregister_hook(reg);
              rtnl_unlock();
      }
      EXPORT_SYMBOL(nf_unregister_hook);
      
      int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
      {
              unsigned int i;
              int err = 0;
      
              for (i = 0; i < n; i++) {
                      err = nf_register_hook(&reg[i]);
                      if (err)
                              goto err;
              }
              return err;
      
      err:
              if (i > 0)
                      nf_unregister_hooks(reg, i);
              return err;
      }
      EXPORT_SYMBOL(nf_register_hooks);
      
      /* Caller MUST take rtnl_lock() */
      int _nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
      {
              unsigned int i;
              int err = 0;
      
              for (i = 0; i < n; i++) {
                      err = _nf_register_hook(&reg[i]);
                      if (err)
                              goto err;
              }
              return err;
      
      err:
              if (i > 0)
                      _nf_unregister_hooks(reg, i);
              return err;
      }
      EXPORT_SYMBOL(_nf_register_hooks);
      
      void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
      {
              while (n-- > 0)
                      nf_unregister_hook(&reg[n]);
      }
      EXPORT_SYMBOL(nf_unregister_hooks);
      
      /* Caller MUST take rtnl_lock */
      void _nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
      {
              while (n-- > 0)
                      _nf_unregister_hook(&reg[n]);
      }
      EXPORT_SYMBOL(_nf_unregister_hooks);
      
      unsigned int nf_iterate(struct sk_buff *skb,
                              struct nf_hook_state *state,
                              struct nf_hook_entry **entryp)
      {
              unsigned int verdict;
      
              /*
               * The caller must not block between calls to this
               * function because of risk of continuing from deleted element.
               */
 1754         while (*entryp) {
 1754                 if (state->thresh > (*entryp)->ops.priority) {
                              *entryp = rcu_dereference((*entryp)->next);
                              continue;
                      }
      
                      /* Optimization: we don't need to hold module
                         reference here, since function can't sleep. --RR */
      repeat:
 1754                 verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
                      if (verdict != NF_ACCEPT) {
      #ifdef CONFIG_NETFILTER_DEBUG
                              if (unlikely((verdict & NF_VERDICT_MASK)
                                                              > NF_MAX_VERDICT)) {
                                      NFDEBUG("Evil return from %p(%u).\n",
                                              (*entryp)->ops.hook, state->hook);
                                      *entryp = rcu_dereference((*entryp)->next);
                                      continue;
                              }
      #endif
   38                         if (verdict != NF_REPEAT)
                                      return verdict;
                              goto repeat;
                      }
 1735                 *entryp = rcu_dereference((*entryp)->next);
              }
 1716         return NF_ACCEPT;
      }
      
      
      /* Returns 1 if okfn() needs to be executed by the caller,
       * -EPERM for NF_DROP, 0 otherwise.  Caller must hold rcu_read_lock. */
      int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
      {
              struct nf_hook_entry *entry;
              unsigned int verdict;
              int ret = 0;
      
 1755         entry = rcu_dereference(state->hook_entries);
      next_hook:
 1754         verdict = nf_iterate(skb, state, &entry);
              if (verdict == NF_ACCEPT || verdict == NF_STOP) {
                      ret = 1;
   35         } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
    5                 kfree_skb(skb);
                      ret = NF_DROP_GETERR(verdict);
                      if (ret == 0)
                              ret = -EPERM;
   33         } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
                      ret = nf_queue(skb, state, &entry, verdict);
                      if (ret == 1 && entry)
                              goto next_hook;
              } else {
                      /* Implicit handling for NF_STOLEN, as well as any other
                       * non conventional verdicts.
                       */
                      ret = 0;
              }
 1716         return ret;
      }
      EXPORT_SYMBOL(nf_hook_slow);
      
      
      int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
      {
   68         if (writable_len > skb->len)
                      return 0;
      
              /* Not exclusive use of packet?  Must copy. */
   68         if (!skb_cloned(skb)) {
   68                 if (writable_len <= skb_headlen(skb))
                              return 1;
              } else if (skb_clone_writable(skb, writable_len))
                      return 1;
      
              if (writable_len <= skb_headlen(skb))
                      writable_len = 0;
              else
                      writable_len -= skb_headlen(skb);
      
   68         return !!__pskb_pull_tail(skb, writable_len);
      }
      EXPORT_SYMBOL(skb_make_writable);
      
      /* This needs to be compiled in any case to avoid dependencies between the
       * nfnetlink_queue code and nf_conntrack.
       */
      struct nfnl_ct_hook __rcu *nfnl_ct_hook __read_mostly;
      EXPORT_SYMBOL_GPL(nfnl_ct_hook);
      
      #if IS_ENABLED(CONFIG_NF_CONNTRACK)
      /* This does not belong here, but locally generated errors need it if connection
         tracking in use: without this, connection may not be in hash table, and hence
         manufactured ICMP or RST packets will not be associated with it. */
      void (*ip_ct_attach)(struct sk_buff *, const struct sk_buff *)
                      __rcu __read_mostly;
      EXPORT_SYMBOL(ip_ct_attach);
      
  103 void nf_ct_attach(struct sk_buff *new, const struct sk_buff *skb)
      {
              void (*attach)(struct sk_buff *, const struct sk_buff *);
      
  163         if (skb->nfct) {
  103                 rcu_read_lock();
  103                 attach = rcu_dereference(ip_ct_attach);
  103                 if (attach)
  103                         attach(new, skb);
  103                 rcu_read_unlock();
              }
  163 }
      EXPORT_SYMBOL(nf_ct_attach);
      
      void (*nf_ct_destroy)(struct nf_conntrack *) __rcu __read_mostly;
      EXPORT_SYMBOL(nf_ct_destroy);
      
      void nf_conntrack_destroy(struct nf_conntrack *nfct)
      {
              void (*destroy)(struct nf_conntrack *);
      
   30         rcu_read_lock();
   30         destroy = rcu_dereference(nf_ct_destroy);
   29         BUG_ON(destroy == NULL);
   29         destroy(nfct);
   28         rcu_read_unlock();
      }
      EXPORT_SYMBOL(nf_conntrack_destroy);
      
      /* Built-in default zone used e.g. by modules. */
      const struct nf_conntrack_zone nf_ct_zone_dflt = {
              .id        = NF_CT_DEFAULT_ZONE_ID,
              .dir        = NF_CT_DEFAULT_ZONE_DIR,
      };
      EXPORT_SYMBOL_GPL(nf_ct_zone_dflt);
      #endif /* CONFIG_NF_CONNTRACK */
      
      #ifdef CONFIG_NF_NAT_NEEDED
      void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);
      EXPORT_SYMBOL(nf_nat_decode_session_hook);
      #endif
      
      static int nf_register_hook_list(struct net *net)
      {
              struct nf_hook_ops *elem;
              int ret;
      
  110         rtnl_lock();
  110         list_for_each_entry(elem, &nf_hook_list, list) {
  110                 ret = nf_register_net_hook(net, elem);
                      if (ret && ret != -ENOENT)
                              goto out_undo;
              }
  110         rtnl_unlock();
              return 0;
      
      out_undo:
              list_for_each_entry_continue_reverse(elem, &nf_hook_list, list)
                      nf_unregister_net_hook(net, elem);
              rtnl_unlock();
              return ret;
      }
      
      static void nf_unregister_hook_list(struct net *net)
      {
              struct nf_hook_ops *elem;
      
              rtnl_lock();
              list_for_each_entry(elem, &nf_hook_list, list)
                      nf_unregister_net_hook(net, elem);
              rtnl_unlock();
      }
      
      static int __net_init netfilter_net_init(struct net *net)
  110 {
              int i, h, ret;
      
  110         for (i = 0; i < ARRAY_SIZE(net->nf.hooks); i++) {
                      for (h = 0; h < NF_MAX_HOOKS; h++)
  110                         RCU_INIT_POINTER(net->nf.hooks[i][h], NULL);
              }
      
      #ifdef CONFIG_PROC_FS
  110         net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
                                                      net->proc_net);
              if (!net->nf.proc_netfilter) {
                      if (!net_eq(net, &init_net))
                              pr_err("cannot create netfilter proc entry");
      
                      return -ENOMEM;
              }
      #endif
  110         ret = nf_register_hook_list(net);
  109         if (ret)
                      remove_proc_entry("netfilter", net->proc_net);
      
              return ret;
      }
      
      static void __net_exit netfilter_net_exit(struct net *net)
      {
              nf_unregister_hook_list(net);
              remove_proc_entry("netfilter", net->proc_net);
      }
      
      static struct pernet_operations netfilter_net_ops = {
              .init = netfilter_net_init,
              .exit = netfilter_net_exit,
      };
      
      int __init netfilter_init(void)
      {
              int ret;
      
              ret = register_pernet_subsys(&netfilter_net_ops);
              if (ret < 0)
                      goto err;
      
              ret = netfilter_log_init();
              if (ret < 0)
                      goto err_pernet;
      
              return 0;
      err_pernet:
              unregister_pernet_subsys(&netfilter_net_ops);
      err:
              return ret;
      }
      #ifndef _TRACE_SYSCALL_H
      #define _TRACE_SYSCALL_H
      
      #include <linux/tracepoint.h>
      #include <linux/unistd.h>
      #include <linux/trace_events.h>
      #include <linux/thread_info.h>
      
      #include <asm/ptrace.h>
      
      
      /*
       * A syscall entry in the ftrace syscalls array.
       *
       * @name: name of the syscall
       * @syscall_nr: number of the syscall
       * @nb_args: number of parameters it takes
       * @types: list of types as strings
       * @args: list of args as strings (args[i] matches types[i])
       * @enter_fields: list of fields for syscall_enter trace event
       * @enter_event: associated syscall_enter trace event
       * @exit_event: associated syscall_exit trace event
       */
      struct syscall_metadata {
              const char        *name;
              int                syscall_nr;
              int                nb_args;
              const char        **types;
              const char        **args;
              struct list_head enter_fields;
      
              struct trace_event_call *enter_event;
              struct trace_event_call *exit_event;
      };
      
      #if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_HAVE_SYSCALL_TRACEPOINTS)
      static inline void syscall_tracepoint_update(struct task_struct *p)
      {
              if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
    1                 set_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT);
              else
  652                 clear_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT);
      }
      #else
      static inline void syscall_tracepoint_update(struct task_struct *p)
      {
      }
      #endif
      
      #endif /* _TRACE_SYSCALL_H */
      /*
       * device.h - generic, centralized driver model
       *
       * Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
       * Copyright (c) 2004-2009 Greg Kroah-Hartman <gregkh@suse.de>
       * Copyright (c) 2008-2009 Novell Inc.
       *
       * This file is released under the GPLv2
       *
       * See Documentation/driver-model/ for more information.
       */
      
      #ifndef _DEVICE_H_
      #define _DEVICE_H_
      
      #include <linux/ioport.h>
      #include <linux/kobject.h>
      #include <linux/klist.h>
      #include <linux/list.h>
      #include <linux/lockdep.h>
      #include <linux/compiler.h>
      #include <linux/types.h>
      #include <linux/mutex.h>
      #include <linux/pinctrl/devinfo.h>
      #include <linux/pm.h>
      #include <linux/atomic.h>
      #include <linux/ratelimit.h>
      #include <linux/uidgid.h>
      #include <linux/gfp.h>
      #include <asm/device.h>
      
      struct device;
      struct device_private;
      struct device_driver;
      struct driver_private;
      struct module;
      struct class;
      struct subsys_private;
      struct bus_type;
      struct device_node;
      struct fwnode_handle;
      struct iommu_ops;
      struct iommu_group;
      struct iommu_fwspec;
      
      struct bus_attribute {
              struct attribute        attr;
              ssize_t (*show)(struct bus_type *bus, char *buf);
              ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
      };
      
      #define BUS_ATTR(_name, _mode, _show, _store)        \
              struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
      #define BUS_ATTR_RW(_name) \
              struct bus_attribute bus_attr_##_name = __ATTR_RW(_name)
      #define BUS_ATTR_RO(_name) \
              struct bus_attribute bus_attr_##_name = __ATTR_RO(_name)
      
      extern int __must_check bus_create_file(struct bus_type *,
                                              struct bus_attribute *);
      extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
      
      /**
       * struct bus_type - The bus type of the device
       *
       * @name:        The name of the bus.
       * @dev_name:        Used for subsystems to enumerate devices like ("foo%u", dev->id).
       * @dev_root:        Default device to use as the parent.
       * @dev_attrs:        Default attributes of the devices on the bus.
       * @bus_groups:        Default attributes of the bus.
       * @dev_groups:        Default attributes of the devices on the bus.
       * @drv_groups: Default attributes of the device drivers on the bus.
       * @match:        Called, perhaps multiple times, whenever a new device or driver
       *                is added for this bus. It should return a positive value if the
       *                given device can be handled by the given driver and zero
       *                otherwise. It may also return error code if determining that
       *                the driver supports the device is not possible. In case of
       *                -EPROBE_DEFER it will queue the device for deferred probing.
       * @uevent:        Called when a device is added, removed, or a few other things
       *                that generate uevents to add the environment variables.
       * @probe:        Called when a new device or driver add to this bus, and callback
       *                the specific driver's probe to initial the matched device.
       * @remove:        Called when a device removed from this bus.
       * @shutdown:        Called at shut-down time to quiesce the device.
       *
       * @online:        Called to put the device back online (after offlining it).
       * @offline:        Called to put the device offline for hot-removal. May fail.
       *
       * @suspend:        Called when a device on this bus wants to go to sleep mode.
       * @resume:        Called to bring a device on this bus out of sleep mode.
       * @pm:                Power management operations of this bus, callback the specific
       *                device driver's pm-ops.
       * @iommu_ops:  IOMMU specific operations for this bus, used to attach IOMMU
       *              driver implementations to a bus and allow the driver to do
       *              bus-specific setup
       * @p:                The private data of the driver core, only the driver core can
       *                touch this.
       * @lock_key:        Lock class key for use by the lock validator
       *
       * A bus is a channel between the processor and one or more devices. For the
       * purposes of the device model, all devices are connected via a bus, even if
       * it is an internal, virtual, "platform" bus. Buses can plug into each other.
       * A USB controller is usually a PCI device, for example. The device model
       * represents the actual connections between buses and the devices they control.
       * A bus is represented by the bus_type structure. It contains the name, the
       * default attributes, the bus' methods, PM operations, and the driver core's
       * private data.
       */
      struct bus_type {
              const char                *name;
              const char                *dev_name;
              struct device                *dev_root;
              struct device_attribute        *dev_attrs;        /* use dev_groups instead */
              const struct attribute_group **bus_groups;
              const struct attribute_group **dev_groups;
              const struct attribute_group **drv_groups;
      
              int (*match)(struct device *dev, struct device_driver *drv);
              int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
              int (*probe)(struct device *dev);
              int (*remove)(struct device *dev);
              void (*shutdown)(struct device *dev);
      
              int (*online)(struct device *dev);
              int (*offline)(struct device *dev);
      
              int (*suspend)(struct device *dev, pm_message_t state);
              int (*resume)(struct device *dev);
      
              const struct dev_pm_ops *pm;
      
              const struct iommu_ops *iommu_ops;
      
              struct subsys_private *p;
              struct lock_class_key lock_key;
      };
      
      extern int __must_check bus_register(struct bus_type *bus);
      
      extern void bus_unregister(struct bus_type *bus);
      
      extern int __must_check bus_rescan_devices(struct bus_type *bus);
      
      /* iterator helpers for buses */
      struct subsys_dev_iter {
              struct klist_iter                ki;
              const struct device_type        *type;
      };
      void subsys_dev_iter_init(struct subsys_dev_iter *iter,
                               struct bus_type *subsys,
                               struct device *start,
                               const struct device_type *type);
      struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter);
      void subsys_dev_iter_exit(struct subsys_dev_iter *iter);
      
      int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,
                           int (*fn)(struct device *dev, void *data));
      struct device *bus_find_device(struct bus_type *bus, struct device *start,
                                     void *data,
                                     int (*match)(struct device *dev, void *data));
      struct device *bus_find_device_by_name(struct bus_type *bus,
                                             struct device *start,
                                             const char *name);
      struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id,
                                              struct device *hint);
      int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
                           void *data, int (*fn)(struct device_driver *, void *));
      void bus_sort_breadthfirst(struct bus_type *bus,
                                 int (*compare)(const struct device *a,
                                                const struct device *b));
      /*
       * Bus notifiers: Get notified of addition/removal of devices
       * and binding/unbinding of drivers to devices.
       * In the long run, it should be a replacement for the platform
       * notify hooks.
       */
      struct notifier_block;
      
      extern int bus_register_notifier(struct bus_type *bus,
                                       struct notifier_block *nb);
      extern int bus_unregister_notifier(struct bus_type *bus,
                                         struct notifier_block *nb);
      
      /* All 4 notifers below get called with the target struct device *
       * as an argument. Note that those functions are likely to be called
       * with the device lock held in the core, so be careful.
       */
      #define BUS_NOTIFY_ADD_DEVICE                0x00000001 /* device added */
      #define BUS_NOTIFY_DEL_DEVICE                0x00000002 /* device to be removed */
      #define BUS_NOTIFY_REMOVED_DEVICE        0x00000003 /* device removed */
      #define BUS_NOTIFY_BIND_DRIVER                0x00000004 /* driver about to be
                                                            bound */
      #define BUS_NOTIFY_BOUND_DRIVER                0x00000005 /* driver bound to device */
      #define BUS_NOTIFY_UNBIND_DRIVER        0x00000006 /* driver about to be
                                                            unbound */
      #define BUS_NOTIFY_UNBOUND_DRIVER        0x00000007 /* driver is unbound
                                                            from the device */
      #define BUS_NOTIFY_DRIVER_NOT_BOUND        0x00000008 /* driver fails to be bound */
      
      extern struct kset *bus_get_kset(struct bus_type *bus);
      extern struct klist *bus_get_device_klist(struct bus_type *bus);
      
      /**
       * enum probe_type - device driver probe type to try
       *        Device drivers may opt in for special handling of their
       *        respective probe routines. This tells the core what to
       *        expect and prefer.
       *
       * @PROBE_DEFAULT_STRATEGY: Used by drivers that work equally well
       *        whether probed synchronously or asynchronously.
       * @PROBE_PREFER_ASYNCHRONOUS: Drivers for "slow" devices which
       *        probing order is not essential for booting the system may
       *        opt into executing their probes asynchronously.
       * @PROBE_FORCE_SYNCHRONOUS: Use this to annotate drivers that need
       *        their probe routines to run synchronously with driver and
       *        device registration (with the exception of -EPROBE_DEFER
       *        handling - re-probing always ends up being done asynchronously).
       *
       * Note that the end goal is to switch the kernel to use asynchronous
       * probing by default, so annotating drivers with
       * %PROBE_PREFER_ASYNCHRONOUS is a temporary measure that allows us
       * to speed up boot process while we are validating the rest of the
       * drivers.
       */
      enum probe_type {
              PROBE_DEFAULT_STRATEGY,
              PROBE_PREFER_ASYNCHRONOUS,
              PROBE_FORCE_SYNCHRONOUS,
      };
      
      /**
       * struct device_driver - The basic device driver structure
       * @name:        Name of the device driver.
       * @bus:        The bus which the device of this driver belongs to.
       * @owner:        The module owner.
       * @mod_name:        Used for built-in modules.
       * @suppress_bind_attrs: Disables bind/unbind via sysfs.
       * @probe_type:        Type of the probe (synchronous or asynchronous) to use.
       * @of_match_table: The open firmware table.
       * @acpi_match_table: The ACPI match table.
       * @probe:        Called to query the existence of a specific device,
       *                whether this driver can work with it, and bind the driver
       *                to a specific device.
       * @remove:        Called when the device is removed from the system to
       *                unbind a device from this driver.
       * @shutdown:        Called at shut-down time to quiesce the device.
       * @suspend:        Called to put the device to sleep mode. Usually to a
       *                low power state.
       * @resume:        Called to bring a device from sleep mode.
       * @groups:        Default attributes that get created by the driver core
       *                automatically.
       * @pm:                Power management operations of the device which matched
       *                this driver.
       * @p:                Driver core's private data, no one other than the driver
       *                core can touch this.
       *
       * The device driver-model tracks all of the drivers known to the system.
       * The main reason for this tracking is to enable the driver core to match
       * up drivers with new devices. Once drivers are known objects within the
       * system, however, a number of other things become possible. Device drivers
       * can export information and configuration variables that are independent
       * of any specific device.
       */
      struct device_driver {
              const char                *name;
              struct bus_type                *bus;
      
              struct module                *owner;
              const char                *mod_name;        /* used for built-in modules */
      
              bool suppress_bind_attrs;        /* disables bind/unbind via sysfs */
              enum probe_type probe_type;
      
              const struct of_device_id        *of_match_table;
              const struct acpi_device_id        *acpi_match_table;
      
              int (*probe) (struct device *dev);
              int (*remove) (struct device *dev);
              void (*shutdown) (struct device *dev);
              int (*suspend) (struct device *dev, pm_message_t state);
              int (*resume) (struct device *dev);
              const struct attribute_group **groups;
      
              const struct dev_pm_ops *pm;
      
              struct driver_private *p;
      };
      
      
      extern int __must_check driver_register(struct device_driver *drv);
      extern void driver_unregister(struct device_driver *drv);
      
      extern struct device_driver *driver_find(const char *name,
                                               struct bus_type *bus);
      extern int driver_probe_done(void);
      extern void wait_for_device_probe(void);
      
      
      /* sysfs interface for exporting driver attributes */
      
      struct driver_attribute {
              struct attribute attr;
              ssize_t (*show)(struct device_driver *driver, char *buf);
              ssize_t (*store)(struct device_driver *driver, const char *buf,
                               size_t count);
      };
      
      #define DRIVER_ATTR(_name, _mode, _show, _store) \
              struct driver_attribute driver_attr_##_name = __ATTR(_name, _mode, _show, _store)
      #define DRIVER_ATTR_RW(_name) \
              struct driver_attribute driver_attr_##_name = __ATTR_RW(_name)
      #define DRIVER_ATTR_RO(_name) \
              struct driver_attribute driver_attr_##_name = __ATTR_RO(_name)
      #define DRIVER_ATTR_WO(_name) \
              struct driver_attribute driver_attr_##_name = __ATTR_WO(_name)
      
      extern int __must_check driver_create_file(struct device_driver *driver,
                                              const struct driver_attribute *attr);
      extern void driver_remove_file(struct device_driver *driver,
                                     const struct driver_attribute *attr);
      
      extern int __must_check driver_for_each_device(struct device_driver *drv,
                                                     struct device *start,
                                                     void *data,
                                                     int (*fn)(struct device *dev,
                                                               void *));
      struct device *driver_find_device(struct device_driver *drv,
                                        struct device *start, void *data,
                                        int (*match)(struct device *dev, void *data));
      
      /**
       * struct subsys_interface - interfaces to device functions
       * @name:       name of the device function
       * @subsys:     subsytem of the devices to attach to
       * @node:       the list of functions registered at the subsystem
       * @add_dev:    device hookup to device function handler
       * @remove_dev: device hookup to device function handler
       *
       * Simple interfaces attached to a subsystem. Multiple interfaces can
       * attach to a subsystem and its devices. Unlike drivers, they do not
       * exclusively claim or control devices. Interfaces usually represent
       * a specific functionality of a subsystem/class of devices.
       */
      struct subsys_interface {
              const char *name;
              struct bus_type *subsys;
              struct list_head node;
              int (*add_dev)(struct device *dev, struct subsys_interface *sif);
              void (*remove_dev)(struct device *dev, struct subsys_interface *sif);
      };
      
      int subsys_interface_register(struct subsys_interface *sif);
      void subsys_interface_unregister(struct subsys_interface *sif);
      
      int subsys_system_register(struct bus_type *subsys,
                                 const struct attribute_group **groups);
      int subsys_virtual_register(struct bus_type *subsys,
                                  const struct attribute_group **groups);
      
      /**
       * struct class - device classes
       * @name:        Name of the class.
       * @owner:        The module owner.
       * @class_attrs: Default attributes of this class.
       * @dev_groups:        Default attributes of the devices that belong to the class.
       * @dev_kobj:        The kobject that represents this class and links it into the hierarchy.
       * @dev_uevent:        Called when a device is added, removed from this class, or a
       *                few other things that generate uevents to add the environment
       *                variables.
       * @devnode:        Callback to provide the devtmpfs.
       * @class_release: Called to release this class.
       * @dev_release: Called to release the device.
       * @suspend:        Used to put the device to sleep mode, usually to a low power
       *                state.
       * @resume:        Used to bring the device from the sleep mode.
       * @shutdown:        Called at shut-down time to quiesce the device.
       * @ns_type:        Callbacks so sysfs can detemine namespaces.
       * @namespace:        Namespace of the device belongs to this class.
       * @pm:                The default device power management operations of this class.
       * @p:                The private data of the driver core, no one other than the
       *                driver core can touch this.
       *
       * A class is a higher-level view of a device that abstracts out low-level
       * implementation details. Drivers may see a SCSI disk or an ATA disk, but,
       * at the class level, they are all simply disks. Classes allow user space
       * to work with devices based on what they do, rather than how they are
       * connected or how they work.
       */
      struct class {
              const char                *name;
              struct module                *owner;
      
              struct class_attribute                *class_attrs;
              const struct attribute_group        **dev_groups;
              struct kobject                        *dev_kobj;
      
              int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
              char *(*devnode)(struct device *dev, umode_t *mode);
      
              void (*class_release)(struct class *class);
              void (*dev_release)(struct device *dev);
      
              int (*suspend)(struct device *dev, pm_message_t state);
              int (*resume)(struct device *dev);
              int (*shutdown)(struct device *dev);
      
              const struct kobj_ns_type_operations *ns_type;
              const void *(*namespace)(struct device *dev);
      
              const struct dev_pm_ops *pm;
      
              struct subsys_private *p;
      };
      
      struct class_dev_iter {
              struct klist_iter                ki;
              const struct device_type        *type;
      };
      
      extern struct kobject *sysfs_dev_block_kobj;
      extern struct kobject *sysfs_dev_char_kobj;
      extern int __must_check __class_register(struct class *class,
                                               struct lock_class_key *key);
      extern void class_unregister(struct class *class);
      
      /* This is a #define to keep the compiler from merging different
       * instances of the __key variable */
      #define class_register(class)                        \
      ({                                                \
              static struct lock_class_key __key;        \
              __class_register(class, &__key);        \
      })
      
      struct class_compat;
      struct class_compat *class_compat_register(const char *name);
      void class_compat_unregister(struct class_compat *cls);
      int class_compat_create_link(struct class_compat *cls, struct device *dev,
                                   struct device *device_link);
      void class_compat_remove_link(struct class_compat *cls, struct device *dev,
                                    struct device *device_link);
      
      extern void class_dev_iter_init(struct class_dev_iter *iter,
                                      struct class *class,
                                      struct device *start,
                                      const struct device_type *type);
      extern struct device *class_dev_iter_next(struct class_dev_iter *iter);
      extern void class_dev_iter_exit(struct class_dev_iter *iter);
      
      extern int class_for_each_device(struct class *class, struct device *start,
                                       void *data,
                                       int (*fn)(struct device *dev, void *data));
      extern struct device *class_find_device(struct class *class,
                                              struct device *start, const void *data,
                                              int (*match)(struct device *, const void *));
      
      struct class_attribute {
              struct attribute attr;
              ssize_t (*show)(struct class *class, struct class_attribute *attr,
                              char *buf);
              ssize_t (*store)(struct class *class, struct class_attribute *attr,
                              const char *buf, size_t count);
      };
      
      #define CLASS_ATTR(_name, _mode, _show, _store) \
              struct class_attribute class_attr_##_name = __ATTR(_name, _mode, _show, _store)
      #define CLASS_ATTR_RW(_name) \
              struct class_attribute class_attr_##_name = __ATTR_RW(_name)
      #define CLASS_ATTR_RO(_name) \
              struct class_attribute class_attr_##_name = __ATTR_RO(_name)
      
      extern int __must_check class_create_file_ns(struct class *class,
                                                   const struct class_attribute *attr,
                                                   const void *ns);
      extern void class_remove_file_ns(struct class *class,
                                       const struct class_attribute *attr,
                                       const void *ns);
      
      static inline int __must_check class_create_file(struct class *class,
                                              const struct class_attribute *attr)
      {
              return class_create_file_ns(class, attr, NULL);
      }
      
      static inline void class_remove_file(struct class *class,
                                           const struct class_attribute *attr)
      {
              return class_remove_file_ns(class, attr, NULL);
      }
      
      /* Simple class attribute that is just a static string */
      struct class_attribute_string {
              struct class_attribute attr;
              char *str;
      };
      
      /* Currently read-only only */
      #define _CLASS_ATTR_STRING(_name, _mode, _str) \
              { __ATTR(_name, _mode, show_class_attr_string, NULL), _str }
      #define CLASS_ATTR_STRING(_name, _mode, _str) \
              struct class_attribute_string class_attr_##_name = \
                      _CLASS_ATTR_STRING(_name, _mode, _str)
      
      extern ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr,
                              char *buf);
      
      struct class_interface {
              struct list_head        node;
              struct class                *class;
      
              int (*add_dev)                (struct device *, struct class_interface *);
              void (*remove_dev)        (struct device *, struct class_interface *);
      };
      
      extern int __must_check class_interface_register(struct class_interface *);
      extern void class_interface_unregister(struct class_interface *);
      
      extern struct class * __must_check __class_create(struct module *owner,
                                                        const char *name,
                                                        struct lock_class_key *key);
      extern void class_destroy(struct class *cls);
      
      /* This is a #define to keep the compiler from merging different
       * instances of the __key variable */
      #define class_create(owner, name)                \
      ({                                                \
              static struct lock_class_key __key;        \
              __class_create(owner, name, &__key);        \
      })
      
      /*
       * The type of device, "struct device" is embedded in. A class
       * or bus can contain devices of different types
       * like "partitions" and "disks", "mouse" and "event".
       * This identifies the device type and carries type-specific
       * information, equivalent to the kobj_type of a kobject.
       * If "name" is specified, the uevent will contain it in
       * the DEVTYPE variable.
       */
      struct device_type {
              const char *name;
              const struct attribute_group **groups;
              int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
              char *(*devnode)(struct device *dev, umode_t *mode,
                               kuid_t *uid, kgid_t *gid);
              void (*release)(struct device *dev);
      
              const struct dev_pm_ops *pm;
      };
      
      /* interface for exporting device attributes */
      struct device_attribute {
              struct attribute        attr;
              ssize_t (*show)(struct device *dev, struct device_attribute *attr,
                              char *buf);
              ssize_t (*store)(struct device *dev, struct device_attribute *attr,
                               const char *buf, size_t count);
      };
      
      struct dev_ext_attribute {
              struct device_attribute attr;
              void *var;
      };
      
      ssize_t device_show_ulong(struct device *dev, struct device_attribute *attr,
                                char *buf);
      ssize_t device_store_ulong(struct device *dev, struct device_attribute *attr,
                                 const char *buf, size_t count);
      ssize_t device_show_int(struct device *dev, struct device_attribute *attr,
                              char *buf);
      ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
                               const char *buf, size_t count);
      ssize_t device_show_bool(struct device *dev, struct device_attribute *attr,
                              char *buf);
      ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
                               const char *buf, size_t count);
      
      #define DEVICE_ATTR(_name, _mode, _show, _store) \
              struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
      #define DEVICE_ATTR_RW(_name) \
              struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
      #define DEVICE_ATTR_RO(_name) \
              struct device_attribute dev_attr_##_name = __ATTR_RO(_name)
      #define DEVICE_ATTR_WO(_name) \
              struct device_attribute dev_attr_##_name = __ATTR_WO(_name)
      #define DEVICE_ULONG_ATTR(_name, _mode, _var) \
              struct dev_ext_attribute dev_attr_##_name = \
                      { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
      #define DEVICE_INT_ATTR(_name, _mode, _var) \
              struct dev_ext_attribute dev_attr_##_name = \
                      { __ATTR(_name, _mode, device_show_int, device_store_int), &(_var) }
      #define DEVICE_BOOL_ATTR(_name, _mode, _var) \
              struct dev_ext_attribute dev_attr_##_name = \
                      { __ATTR(_name, _mode, device_show_bool, device_store_bool), &(_var) }
      #define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \
              struct device_attribute dev_attr_##_name =                \
                      __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)
      
      extern int device_create_file(struct device *device,
                                    const struct device_attribute *entry);
      extern void device_remove_file(struct device *dev,
                                     const struct device_attribute *attr);
      extern bool device_remove_file_self(struct device *dev,
                                          const struct device_attribute *attr);
      extern int __must_check device_create_bin_file(struct device *dev,
                                              const struct bin_attribute *attr);
      extern void device_remove_bin_file(struct device *dev,
                                         const struct bin_attribute *attr);
      
      /* device resource management */
      typedef void (*dr_release_t)(struct device *dev, void *res);
      typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data);
      
      #ifdef CONFIG_DEBUG_DEVRES
      extern void *__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp,
                                       int nid, const char *name) __malloc;
      #define devres_alloc(release, size, gfp) \
              __devres_alloc_node(release, size, gfp, NUMA_NO_NODE, #release)
      #define devres_alloc_node(release, size, gfp, nid) \
              __devres_alloc_node(release, size, gfp, nid, #release)
      #else
      extern void *devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp,
                                     int nid) __malloc;
      static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
      {
              return devres_alloc_node(release, size, gfp, NUMA_NO_NODE);
      }
      #endif
      
      extern void devres_for_each_res(struct device *dev, dr_release_t release,
                                      dr_match_t match, void *match_data,
                                      void (*fn)(struct device *, void *, void *),
                                      void *data);
      extern void devres_free(void *res);
      extern void devres_add(struct device *dev, void *res);
      extern void *devres_find(struct device *dev, dr_release_t release,
                               dr_match_t match, void *match_data);
      extern void *devres_get(struct device *dev, void *new_res,
                              dr_match_t match, void *match_data);
      extern void *devres_remove(struct device *dev, dr_release_t release,
                                 dr_match_t match, void *match_data);
      extern int devres_destroy(struct device *dev, dr_release_t release,
                                dr_match_t match, void *match_data);
      extern int devres_release(struct device *dev, dr_release_t release,
                                dr_match_t match, void *match_data);
      
      /* devres group */
      extern void * __must_check devres_open_group(struct device *dev, void *id,
                                                   gfp_t gfp);
      extern void devres_close_group(struct device *dev, void *id);
      extern void devres_remove_group(struct device *dev, void *id);
      extern int devres_release_group(struct device *dev, void *id);
      
      /* managed devm_k.alloc/kfree for device drivers */
      extern void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) __malloc;
      extern __printf(3, 0)
      char *devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt,
                            va_list ap) __malloc;
      extern __printf(3, 4)
      char *devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...) __malloc;
      static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
      {
              return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
      }
      static inline void *devm_kmalloc_array(struct device *dev,
                                             size_t n, size_t size, gfp_t flags)
      {
              if (size != 0 && n > SIZE_MAX / size)
                      return NULL;
              return devm_kmalloc(dev, n * size, flags);
      }
      static inline void *devm_kcalloc(struct device *dev,
                                       size_t n, size_t size, gfp_t flags)
      {
              return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
      }
      extern void devm_kfree(struct device *dev, void *p);
      extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) __malloc;
      extern void *devm_kmemdup(struct device *dev, const void *src, size_t len,
                                gfp_t gfp);
      
      extern unsigned long devm_get_free_pages(struct device *dev,
                                               gfp_t gfp_mask, unsigned int order);
      extern void devm_free_pages(struct device *dev, unsigned long addr);
      
      void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
      
      /* allows to add/remove a custom action to devres stack */
      int devm_add_action(struct device *dev, void (*action)(void *), void *data);
      void devm_remove_action(struct device *dev, void (*action)(void *), void *data);
      
      static inline int devm_add_action_or_reset(struct device *dev,
                                                 void (*action)(void *), void *data)
      {
              int ret;
      
              ret = devm_add_action(dev, action, data);
              if (ret)
                      action(data);
      
              return ret;
      }
      
      struct device_dma_parameters {
              /*
               * a low level driver may set these to teach IOMMU code about
               * sg limitations.
               */
              unsigned int max_segment_size;
              unsigned long segment_boundary_mask;
      };
      
      /**
       * struct device - The basic device structure
       * @parent:        The device's "parent" device, the device to which it is attached.
       *                 In most cases, a parent device is some sort of bus or host
       *                 controller. If parent is NULL, the device, is a top-level device,
       *                 which is not usually what you want.
       * @p:                Holds the private data of the driver core portions of the device.
       *                 See the comment of the struct device_private for detail.
       * @kobj:        A top-level, abstract class from which other classes are derived.
       * @init_name:        Initial name of the device.
       * @type:        The type of device.
       *                 This identifies the device type and carries type-specific
       *                 information.
       * @mutex:        Mutex to synchronize calls to its driver.
       * @bus:        Type of bus device is on.
       * @driver:        Which driver has allocated this
       * @platform_data: Platform data specific to the device.
       *                 Example: For devices on custom boards, as typical of embedded
       *                 and SOC based hardware, Linux often uses platform_data to point
       *                 to board-specific structures describing devices and how they
       *                 are wired.  That can include what ports are available, chip
       *                 variants, which GPIO pins act in what additional roles, and so
       *                 on.  This shrinks the "Board Support Packages" (BSPs) and
       *                 minimizes board-specific #ifdefs in drivers.
       * @driver_data: Private pointer for driver specific info.
       * @power:        For device power management.
       *                 See Documentation/power/devices.txt for details.
       * @pm_domain:        Provide callbacks that are executed during system suspend,
       *                 hibernation, system resume and during runtime PM transitions
       *                 along with subsystem-level and driver-level callbacks.
       * @pins:        For device pin management.
       *                See Documentation/pinctrl.txt for details.
       * @msi_list:        Hosts MSI descriptors
       * @msi_domain: The generic MSI domain this device is using.
       * @numa_node:        NUMA node this device is close to.
       * @dma_mask:        Dma mask (if dma'ble device).
       * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
       *                 hardware supports 64-bit addresses for consistent allocations
       *                 such descriptors.
       * @dma_pfn_offset: offset of DMA memory range relatively of RAM
       * @dma_parms:        A low level driver may set these to teach IOMMU code about
       *                 segment limitations.
       * @dma_pools:        Dma pools (if dma'ble device).
       * @dma_mem:        Internal for coherent mem override.
       * @cma_area:        Contiguous memory area for dma allocations
       * @archdata:        For arch-specific additions.
       * @of_node:        Associated device tree node.
       * @fwnode:        Associated device node supplied by platform firmware.
       * @devt:        For creating the sysfs "dev".
       * @id:                device instance
       * @devres_lock: Spinlock to protect the resource of the device.
       * @devres_head: The resources list of the device.
       * @knode_class: The node used to add the device to the class list.
       * @class:        The class of the device.
       * @groups:        Optional attribute groups.
       * @release:        Callback to free the device after all references have
       *                 gone away. This should be set by the allocator of the
       *                 device (i.e. the bus driver that discovered the device).
       * @iommu_group: IOMMU group the device belongs to.
       * @iommu_fwspec: IOMMU-specific properties supplied by firmware.
       *
       * @offline_disabled: If set, the device is permanently online.
       * @offline:        Set after successful invocation of bus type's .offline().
       *
       * At the lowest level, every device in a Linux system is represented by an
       * instance of struct device. The device structure contains the information
       * that the device model core needs to model the system. Most subsystems,
       * however, track additional information about the devices they host. As a
       * result, it is rare for devices to be represented by bare device structures;
       * instead, that structure, like kobject structures, is usually embedded within
       * a higher-level representation of the device.
       */
      struct device {
              struct device                *parent;
      
              struct device_private        *p;
      
              struct kobject kobj;
              const char                *init_name; /* initial name of the device */
              const struct device_type *type;
      
              struct mutex                mutex;        /* mutex to synchronize calls to
                                               * its driver.
                                               */
      
              struct bus_type        *bus;                /* type of bus device is on */
              struct device_driver *driver;        /* which driver has allocated this
                                                 device */
              void                *platform_data;        /* Platform specific data, device
                                                 core doesn't touch it */
              void                *driver_data;        /* Driver data, set and get with
                                                 dev_set/get_drvdata */
              struct dev_pm_info        power;
              struct dev_pm_domain        *pm_domain;
      
      #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
              struct irq_domain        *msi_domain;
      #endif
      #ifdef CONFIG_PINCTRL
              struct dev_pin_info        *pins;
      #endif
      #ifdef CONFIG_GENERIC_MSI_IRQ
              struct list_head        msi_list;
      #endif
      
      #ifdef CONFIG_NUMA
              int                numa_node;        /* NUMA node this device is close to */
      #endif
              u64                *dma_mask;        /* dma mask (if dma'able device) */
              u64                coherent_dma_mask;/* Like dma_mask, but for
                                                   alloc_coherent mappings as
                                                   not all hardware supports
                                                   64 bit addresses for consistent
                                                   allocations such descriptors. */
              unsigned long        dma_pfn_offset;
      
              struct device_dma_parameters *dma_parms;
      
              struct list_head        dma_pools;        /* dma pools (if dma'ble) */
      
              struct dma_coherent_mem        *dma_mem; /* internal for coherent mem
                                                   override */
      #ifdef CONFIG_DMA_CMA
              struct cma *cma_area;                /* contiguous memory area for dma
                                                 allocations */
      #endif
              /* arch specific additions */
              struct dev_archdata        archdata;
      
              struct device_node        *of_node; /* associated device tree node */
              struct fwnode_handle        *fwnode; /* firmware device node */
      
              dev_t                        devt;        /* dev_t, creates the sysfs "dev" */
              u32                        id;        /* device instance */
      
              spinlock_t                devres_lock;
              struct list_head        devres_head;
      
              struct klist_node        knode_class;
              struct class                *class;
              const struct attribute_group **groups;        /* optional groups */
      
              void        (*release)(struct device *dev);
              struct iommu_group        *iommu_group;
              struct iommu_fwspec        *iommu_fwspec;
      
              bool                        offline_disabled:1;
              bool                        offline:1;
      };
      
      static inline struct device *kobj_to_dev(struct kobject *kobj)
      {
  997         return container_of(kobj, struct device, kobj);
      }
      
      /* Get the wakeup routines, which depend on struct device */
      #include <linux/pm_wakeup.h>
      
      static inline const char *dev_name(const struct device *dev)
      {
              /* Use the init name until the kobject becomes available */
  935         if (dev->init_name)
                      return dev->init_name;
      
 1020         return kobject_name(&dev->kobj);
      }
      
      extern __printf(2, 3)
      int dev_set_name(struct device *dev, const char *name, ...);
      
      #ifdef CONFIG_NUMA
      static inline int dev_to_node(struct device *dev)
      {
              return dev->numa_node;
      }
      static inline void set_dev_node(struct device *dev, int node)
      {
              dev->numa_node = node;
      }
      #else
      static inline int dev_to_node(struct device *dev)
      {
              return -1;
      }
      static inline void set_dev_node(struct device *dev, int node)
      {
      }
      #endif
      
      static inline struct irq_domain *dev_get_msi_domain(const struct device *dev)
      {
      #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
              return dev->msi_domain;
      #else
              return NULL;
      #endif
      }
      
      static inline void dev_set_msi_domain(struct device *dev, struct irq_domain *d)
      {
      #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
              dev->msi_domain = d;
      #endif
      }
      
      static inline void *dev_get_drvdata(const struct device *dev)
      {
   57         return dev->driver_data;
      }
      
      static inline void dev_set_drvdata(struct device *dev, void *data)
      {
              dev->driver_data = data;
      }
      
      static inline struct pm_subsys_data *dev_to_psd(struct device *dev)
      {
              return dev ? dev->power.subsys_data : NULL;
      }
      
      static inline unsigned int dev_get_uevent_suppress(const struct device *dev)
      {
              return dev->kobj.uevent_suppress;
      }
      
      static inline void dev_set_uevent_suppress(struct device *dev, int val)
      {
   69         dev->kobj.uevent_suppress = val;
      }
      
      static inline int device_is_registered(struct device *dev)
      {
    8         return dev->kobj.state_in_sysfs;
      }
      
      static inline void device_enable_async_suspend(struct device *dev)
      {
              if (!dev->power.is_prepared)
   14                 dev->power.async_suspend = true;
      }
      
      static inline void device_disable_async_suspend(struct device *dev)
      {
              if (!dev->power.is_prepared)
                      dev->power.async_suspend = false;
      }
      
      static inline bool device_async_suspend_enabled(struct device *dev)
      {
              return !!dev->power.async_suspend;
      }
      
      static inline void dev_pm_syscore_device(struct device *dev, bool val)
      {
      #ifdef CONFIG_PM_SLEEP
              dev->power.syscore = val;
      #endif
      }
      
      static inline void device_lock(struct device *dev)
      {
   17         mutex_lock(&dev->mutex);
      }
      
      static inline int device_lock_interruptible(struct device *dev)
      {
              return mutex_lock_interruptible(&dev->mutex);
      }
      
      static inline int device_trylock(struct device *dev)
      {
              return mutex_trylock(&dev->mutex);
      }
      
      static inline void device_unlock(struct device *dev)
      {
              mutex_unlock(&dev->mutex);
      }
      
      static inline void device_lock_assert(struct device *dev)
      {
              lockdep_assert_held(&dev->mutex);
      }
      
      static inline struct device_node *dev_of_node(struct device *dev)
      {
              if (!IS_ENABLED(CONFIG_OF))
                      return NULL;
              return dev->of_node;
      }
      
      void driver_init(void);
      
      /*
       * High level routines for use by the bus drivers
       */
      extern int __must_check device_register(struct device *dev);
      extern void device_unregister(struct device *dev);
      extern void device_initialize(struct device *dev);
      extern int __must_check device_add(struct device *dev);
      extern void device_del(struct device *dev);
      extern int device_for_each_child(struct device *dev, void *data,
                           int (*fn)(struct device *dev, void *data));
      extern int device_for_each_child_reverse(struct device *dev, void *data,
                           int (*fn)(struct device *dev, void *data));
      extern struct device *device_find_child(struct device *dev, void *data,
                                      int (*match)(struct device *dev, void *data));
      extern int device_rename(struct device *dev, const char *new_name);
      extern int device_move(struct device *dev, struct device *new_parent,
                             enum dpm_order dpm_order);
      extern const char *device_get_devnode(struct device *dev,
                                            umode_t *mode, kuid_t *uid, kgid_t *gid,
                                            const char **tmp);
      
      static inline bool device_supports_offline(struct device *dev)
      {
  580         return dev->bus && dev->bus->offline && dev->bus->online;
      }
      
      extern void lock_device_hotplug(void);
      extern void unlock_device_hotplug(void);
      extern int lock_device_hotplug_sysfs(void);
      extern int device_offline(struct device *dev);
      extern int device_online(struct device *dev);
      extern void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
      extern void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
      
      /*
       * Root device objects for grouping under /sys/devices
       */
      extern struct device *__root_device_register(const char *name,
                                                   struct module *owner);
      
      /* This is a macro to avoid include problems with THIS_MODULE */
      #define root_device_register(name) \
              __root_device_register(name, THIS_MODULE)
      
      extern void root_device_unregister(struct device *root);
      
      static inline void *dev_get_platdata(const struct device *dev)
      {
              return dev->platform_data;
      }
      
      /*
       * Manual binding of a device to driver. See drivers/base/bus.c
       * for information on use.
       */
      extern int __must_check device_bind_driver(struct device *dev);
      extern void device_release_driver(struct device *dev);
      extern int  __must_check device_attach(struct device *dev);
      extern int __must_check driver_attach(struct device_driver *drv);
      extern void device_initial_probe(struct device *dev);
      extern int __must_check device_reprobe(struct device *dev);
      
      extern bool device_is_bound(struct device *dev);
      
      /*
       * Easy functions for dynamically creating devices on the fly
       */
      extern __printf(5, 0)
      struct device *device_create_vargs(struct class *cls, struct device *parent,
                                         dev_t devt, void *drvdata,
                                         const char *fmt, va_list vargs);
      extern __printf(5, 6)
      struct device *device_create(struct class *cls, struct device *parent,
                                   dev_t devt, void *drvdata,
                                   const char *fmt, ...);
      extern __printf(6, 7)
      struct device *device_create_with_groups(struct class *cls,
                                   struct device *parent, dev_t devt, void *drvdata,
                                   const struct attribute_group **groups,
                                   const char *fmt, ...);
      extern void device_destroy(struct class *cls, dev_t devt);
      
      /*
       * Platform "fixup" functions - allow the platform to have their say
       * about devices and actions that the general device layer doesn't
       * know about.
       */
      /* Notify platform of device discovery */
      extern int (*platform_notify)(struct device *dev);
      
      extern int (*platform_notify_remove)(struct device *dev);
      
      
      /*
       * get_device - atomically increment the reference count for the device.
       *
       */
      extern struct device *get_device(struct device *dev);
      extern void put_device(struct device *dev);
      
      #ifdef CONFIG_DEVTMPFS
      extern int devtmpfs_create_node(struct device *dev);
      extern int devtmpfs_delete_node(struct device *dev);
      extern int devtmpfs_mount(const char *mntdir);
      #else
      static inline int devtmpfs_create_node(struct device *dev) { return 0; }
      static inline int devtmpfs_delete_node(struct device *dev) { return 0; }
      static inline int devtmpfs_mount(const char *mountpoint) { return 0; }
      #endif
      
      /* drivers/base/power/shutdown.c */
      extern void device_shutdown(void);
      
      /* debugging and troubleshooting/diagnostic helpers. */
      extern const char *dev_driver_string(const struct device *dev);
      
      
      #ifdef CONFIG_PRINTK
      
      extern __printf(3, 0)
      int dev_vprintk_emit(int level, const struct device *dev,
                           const char *fmt, va_list args);
      extern __printf(3, 4)
      int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...);
      
      extern __printf(3, 4)
      void dev_printk(const char *level, const struct device *dev,
                      const char *fmt, ...);
      extern __printf(2, 3)
      void dev_emerg(const struct device *dev, const char *fmt, ...);
      extern __printf(2, 3)
      void dev_alert(const struct device *dev, const char *fmt, ...);
      extern __printf(2, 3)
      void dev_crit(const struct device *dev, const char *fmt, ...);
      extern __printf(2, 3)
      void dev_err(const struct device *dev, const char *fmt, ...);
      extern __printf(2, 3)
      void dev_warn(const struct device *dev, const char *fmt, ...);
      extern __printf(2, 3)
      void dev_notice(const struct device *dev, const char *fmt, ...);
      extern __printf(2, 3)
      void _dev_info(const struct device *dev, const char *fmt, ...);
      
      #else
      
      static inline __printf(3, 0)
      int dev_vprintk_emit(int level, const struct device *dev,
                           const char *fmt, va_list args)
      { return 0; }
      static inline __printf(3, 4)
      int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...)
      { return 0; }
      
      static inline void __dev_printk(const char *level, const struct device *dev,
                                      struct va_format *vaf)
      {}
      static inline __printf(3, 4)
      void dev_printk(const char *level, const struct device *dev,
                      const char *fmt, ...)
      {}
      
      static inline __printf(2, 3)
      void dev_emerg(const struct device *dev, const char *fmt, ...)
      {}
      static inline __printf(2, 3)
      void dev_crit(const struct device *dev, const char *fmt, ...)
      {}
      static inline __printf(2, 3)
      void dev_alert(const struct device *dev, const char *fmt, ...)
      {}
      static inline __printf(2, 3)
      void dev_err(const struct device *dev, const char *fmt, ...)
      {}
      static inline __printf(2, 3)
      void dev_warn(const struct device *dev, const char *fmt, ...)
      {}
      static inline __printf(2, 3)
      void dev_notice(const struct device *dev, const char *fmt, ...)
      {}
      static inline __printf(2, 3)
      void _dev_info(const struct device *dev, const char *fmt, ...)
      {}
      
      #endif
      
      /*
       * Stupid hackaround for existing uses of non-printk uses dev_info
       *
       * Note that the definition of dev_info below is actually _dev_info
       * and a macro is used to avoid redefining dev_info
       */
      
      #define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg)
      
      #if defined(CONFIG_DYNAMIC_DEBUG)
      #define dev_dbg(dev, format, ...)                     \
      do {                                                     \
              dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
      } while (0)
      #elif defined(DEBUG)
      #define dev_dbg(dev, format, arg...)                \
              dev_printk(KERN_DEBUG, dev, format, ##arg)
      #else
      #define dev_dbg(dev, format, arg...)                                \
      ({                                                                \
              if (0)                                                        \
                      dev_printk(KERN_DEBUG, dev, format, ##arg);        \
      })
      #endif
      
      #ifdef CONFIG_PRINTK
      #define dev_level_once(dev_level, dev, fmt, ...)                        \
      do {                                                                        \
              static bool __print_once __read_mostly;                                \
                                                                              \
              if (!__print_once) {                                                \
                      __print_once = true;                                        \
                      dev_level(dev, fmt, ##__VA_ARGS__);                        \
              }                                                                \
      } while (0)
      #else
      #define dev_level_once(dev_level, dev, fmt, ...)                        \
      do {                                                                        \
              if (0)                                                                \
                      dev_level(dev, fmt, ##__VA_ARGS__);                        \
      } while (0)
      #endif
      
      #define dev_emerg_once(dev, fmt, ...)                                        \
              dev_level_once(dev_emerg, dev, fmt, ##__VA_ARGS__)
      #define dev_alert_once(dev, fmt, ...)                                        \
              dev_level_once(dev_alert, dev, fmt, ##__VA_ARGS__)
      #define dev_crit_once(dev, fmt, ...)                                        \
              dev_level_once(dev_crit, dev, fmt, ##__VA_ARGS__)
      #define dev_err_once(dev, fmt, ...)                                        \
              dev_level_once(dev_err, dev, fmt, ##__VA_ARGS__)
      #define dev_warn_once(dev, fmt, ...)                                        \
              dev_level_once(dev_warn, dev, fmt, ##__VA_ARGS__)
      #define dev_notice_once(dev, fmt, ...)                                        \
              dev_level_once(dev_notice, dev, fmt, ##__VA_ARGS__)
      #define dev_info_once(dev, fmt, ...)                                        \
              dev_level_once(dev_info, dev, fmt, ##__VA_ARGS__)
      #define dev_dbg_once(dev, fmt, ...)                                        \
              dev_level_once(dev_dbg, dev, fmt, ##__VA_ARGS__)
      
      #define dev_level_ratelimited(dev_level, dev, fmt, ...)                        \
      do {                                                                        \
              static DEFINE_RATELIMIT_STATE(_rs,                                \
                                            DEFAULT_RATELIMIT_INTERVAL,        \
                                            DEFAULT_RATELIMIT_BURST);                \
              if (__ratelimit(&_rs))                                                \
                      dev_level(dev, fmt, ##__VA_ARGS__);                        \
      } while (0)
      
      #define dev_emerg_ratelimited(dev, fmt, ...)                                \
              dev_level_ratelimited(dev_emerg, dev, fmt, ##__VA_ARGS__)
      #define dev_alert_ratelimited(dev, fmt, ...)                                \
              dev_level_ratelimited(dev_alert, dev, fmt, ##__VA_ARGS__)
      #define dev_crit_ratelimited(dev, fmt, ...)                                \
              dev_level_ratelimited(dev_crit, dev, fmt, ##__VA_ARGS__)
      #define dev_err_ratelimited(dev, fmt, ...)                                \
              dev_level_ratelimited(dev_err, dev, fmt, ##__VA_ARGS__)
      #define dev_warn_ratelimited(dev, fmt, ...)                                \
              dev_level_ratelimited(dev_warn, dev, fmt, ##__VA_ARGS__)
      #define dev_notice_ratelimited(dev, fmt, ...)                                \
              dev_level_ratelimited(dev_notice, dev, fmt, ##__VA_ARGS__)
      #define dev_info_ratelimited(dev, fmt, ...)                                \
              dev_level_ratelimited(dev_info, dev, fmt, ##__VA_ARGS__)
      #if defined(CONFIG_DYNAMIC_DEBUG)
      /* descriptor check is first to prevent flooding with "callbacks suppressed" */
      #define dev_dbg_ratelimited(dev, fmt, ...)                                \
      do {                                                                        \
              static DEFINE_RATELIMIT_STATE(_rs,                                \
                                            DEFAULT_RATELIMIT_INTERVAL,        \
                                            DEFAULT_RATELIMIT_BURST);                \
              DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);                        \
              if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT) &&        \
                  __ratelimit(&_rs))                                                \
                      __dynamic_dev_dbg(&descriptor, dev, fmt,                \
                                        ##__VA_ARGS__);                        \
      } while (0)
      #elif defined(DEBUG)
      #define dev_dbg_ratelimited(dev, fmt, ...)                                \
      do {                                                                        \
              static DEFINE_RATELIMIT_STATE(_rs,                                \
                                            DEFAULT_RATELIMIT_INTERVAL,        \
                                            DEFAULT_RATELIMIT_BURST);                \
              if (__ratelimit(&_rs))                                                \
                      dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__);        \
      } while (0)
      #else
      #define dev_dbg_ratelimited(dev, fmt, ...)                                \
      do {                                                                        \
              if (0)                                                                \
                      dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__);        \
      } while (0)
      #endif
      
      #ifdef VERBOSE_DEBUG
      #define dev_vdbg        dev_dbg
      #else
      #define dev_vdbg(dev, format, arg...)                                \
      ({                                                                \
              if (0)                                                        \
                      dev_printk(KERN_DEBUG, dev, format, ##arg);        \
      })
      #endif
      
      /*
       * dev_WARN*() acts like dev_printk(), but with the key difference of
       * using WARN/WARN_ONCE to include file/line information and a backtrace.
       */
      #define dev_WARN(dev, format, arg...) \
              WARN(1, "%s %s: " format, dev_driver_string(dev), dev_name(dev), ## arg);
      
      #define dev_WARN_ONCE(dev, condition, format, arg...) \
              WARN_ONCE(condition, "%s %s: " format, \
                              dev_driver_string(dev), dev_name(dev), ## arg)
      
      /* Create alias, so I can be autoloaded. */
      #define MODULE_ALIAS_CHARDEV(major,minor) \
              MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
      #define MODULE_ALIAS_CHARDEV_MAJOR(major) \
              MODULE_ALIAS("char-major-" __stringify(major) "-*")
      
      #ifdef CONFIG_SYSFS_DEPRECATED
      extern long sysfs_deprecated;
      #else
      #define sysfs_deprecated 0
      #endif
      
      /**
       * module_driver() - Helper macro for drivers that don't do anything
       * special in module init/exit. This eliminates a lot of boilerplate.
       * Each module may only use this macro once, and calling it replaces
       * module_init() and module_exit().
       *
       * @__driver: driver name
       * @__register: register function for this driver type
       * @__unregister: unregister function for this driver type
       * @...: Additional arguments to be passed to __register and __unregister.
       *
       * Use this macro to construct bus specific macros for registering
       * drivers, and do not use it on its own.
       */
      #define module_driver(__driver, __register, __unregister, ...) \
      static int __init __driver##_init(void) \
      { \
              return __register(&(__driver) , ##__VA_ARGS__); \
      } \
      module_init(__driver##_init); \
      static void __exit __driver##_exit(void) \
      { \
              __unregister(&(__driver) , ##__VA_ARGS__); \
      } \
      module_exit(__driver##_exit);
      
      /**
       * builtin_driver() - Helper macro for drivers that don't do anything
       * special in init and have no exit. This eliminates some boilerplate.
       * Each driver may only use this macro once, and calling it replaces
       * device_initcall (or in some cases, the legacy __initcall).  This is
       * meant to be a direct parallel of module_driver() above but without
       * the __exit stuff that is not used for builtin cases.
       *
       * @__driver: driver name
       * @__register: register function for this driver type
       * @...: Additional arguments to be passed to __register
       *
       * Use this macro to construct bus specific macros for registering
       * drivers, and do not use it on its own.
       */
      #define builtin_driver(__driver, __register, ...) \
      static int __init __driver##_init(void) \
      { \
              return __register(&(__driver) , ##__VA_ARGS__); \
      } \
      device_initcall(__driver##_init);
      
      #endif /* _DEVICE_H_ */
      /* Netfilter messages via netlink socket. Allows for user space
       * protocol helpers and general trouble making from userspace.
       *
       * (C) 2001 by Jay Schulist <jschlst@samba.org>,
       * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
       * (C) 2005,2007 by Pablo Neira Ayuso <pablo@netfilter.org>
       *
       * Initial netfilter messages via netlink development funded and
       * generally made possible by Network Robots, Inc. (www.networkrobots.com)
       *
       * Further development of this code funded by Astaro AG (http://www.astaro.com)
       *
       * This software may be used and distributed according to the terms
       * of the GNU General Public License, incorporated herein by reference.
       */
      
      #include <linux/module.h>
      #include <linux/types.h>
      #include <linux/socket.h>
      #include <linux/kernel.h>
      #include <linux/string.h>
      #include <linux/sockios.h>
      #include <linux/net.h>
      #include <linux/skbuff.h>
      #include <asm/uaccess.h>
      #include <net/sock.h>
      #include <linux/init.h>
      
      #include <net/netlink.h>
      #include <linux/netfilter/nfnetlink.h>
      
      MODULE_LICENSE("GPL");
      MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
      MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
      
      #define nfnl_dereference_protected(id) \
              rcu_dereference_protected(table[(id)].subsys, \
                                        lockdep_nfnl_is_held((id)))
      
      static char __initdata nfversion[] = "0.30";
      
      static struct {
              struct mutex                                mutex;
              const struct nfnetlink_subsystem __rcu        *subsys;
      } table[NFNL_SUBSYS_COUNT];
      
      static const int nfnl_group2type[NFNLGRP_MAX+1] = {
              [NFNLGRP_CONNTRACK_NEW]                = NFNL_SUBSYS_CTNETLINK,
              [NFNLGRP_CONNTRACK_UPDATE]        = NFNL_SUBSYS_CTNETLINK,
              [NFNLGRP_CONNTRACK_DESTROY]        = NFNL_SUBSYS_CTNETLINK,
              [NFNLGRP_CONNTRACK_EXP_NEW]        = NFNL_SUBSYS_CTNETLINK_EXP,
              [NFNLGRP_CONNTRACK_EXP_UPDATE]        = NFNL_SUBSYS_CTNETLINK_EXP,
              [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP,
              [NFNLGRP_NFTABLES]                = NFNL_SUBSYS_NFTABLES,
              [NFNLGRP_ACCT_QUOTA]                = NFNL_SUBSYS_ACCT,
              [NFNLGRP_NFTRACE]                = NFNL_SUBSYS_NFTABLES,
      };
      
      void nfnl_lock(__u8 subsys_id)
      {
    7         mutex_lock(&table[subsys_id].mutex);
      }
      EXPORT_SYMBOL_GPL(nfnl_lock);
      
      void nfnl_unlock(__u8 subsys_id)
      {
    8         mutex_unlock(&table[subsys_id].mutex);
      }
      EXPORT_SYMBOL_GPL(nfnl_unlock);
      
      #ifdef CONFIG_PROVE_LOCKING
      bool lockdep_nfnl_is_held(u8 subsys_id)
      {
  112         return lockdep_is_held(&table[subsys_id].mutex);
      }
      EXPORT_SYMBOL_GPL(lockdep_nfnl_is_held);
      #endif
      
      int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
      {
              nfnl_lock(n->subsys_id);
              if (table[n->subsys_id].subsys) {
                      nfnl_unlock(n->subsys_id);
                      return -EBUSY;
              }
              rcu_assign_pointer(table[n->subsys_id].subsys, n);
              nfnl_unlock(n->subsys_id);
      
              return 0;
      }
      EXPORT_SYMBOL_GPL(nfnetlink_subsys_register);
      
      int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n)
      {
              nfnl_lock(n->subsys_id);
              table[n->subsys_id].subsys = NULL;
              nfnl_unlock(n->subsys_id);
              synchronize_rcu();
              return 0;
      }
      EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
      
      static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type)
      {
              u_int8_t subsys_id = NFNL_SUBSYS_ID(type);
      
  118         if (subsys_id >= NFNL_SUBSYS_COUNT)
                      return NULL;
      
  123         return rcu_dereference(table[subsys_id].subsys);
      }
      
      static inline const struct nfnl_callback *
      nfnetlink_find_client(u_int16_t type, const struct nfnetlink_subsystem *ss)
      {
              u_int8_t cb_id = NFNL_MSG_TYPE(type);
      
  114         if (cb_id >= ss->cb_count)
                      return NULL;
      
  113         return &ss->cb[cb_id];
      }
      
      int nfnetlink_has_listeners(struct net *net, unsigned int group)
      {
  913         return netlink_has_listeners(net->nfnl, group);
      }
      EXPORT_SYMBOL_GPL(nfnetlink_has_listeners);
      
      int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 portid,
                         unsigned int group, int echo, gfp_t flags)
      {
    1         return nlmsg_notify(net->nfnl, skb, portid, group, echo, flags);
      }
      EXPORT_SYMBOL_GPL(nfnetlink_send);
      
      int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error)
      {
              return netlink_set_err(net->nfnl, portid, group, error);
      }
      EXPORT_SYMBOL_GPL(nfnetlink_set_err);
      
      int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid,
                            int flags)
      {
              return netlink_unicast(net->nfnl, skb, portid, flags);
      }
      EXPORT_SYMBOL_GPL(nfnetlink_unicast);
      
      /* Process one complete nfnetlink message. */
      static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
      {
  118         struct net *net = sock_net(skb->sk);
              const struct nfnl_callback *nc;
              const struct nfnetlink_subsystem *ss;
              int type, err;
      
              /* All the messages must at least contain nfgenmsg */
  119         if (nlmsg_len(nlh) < sizeof(struct nfgenmsg))
                      return 0;
      
              type = nlh->nlmsg_type;
      replay:
  118         rcu_read_lock();
  118         ss = nfnetlink_get_subsys(type);
  118         if (!ss) {
      #ifdef CONFIG_MODULES
    6                 rcu_read_unlock();
                      request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
    4                 rcu_read_lock();
    4                 ss = nfnetlink_get_subsys(type);
    4                 if (!ss)
      #endif
                      {
    4                         rcu_read_unlock();
                              return -EINVAL;
                      }
              }
      
  114         nc = nfnetlink_find_client(type, ss);
              if (!nc) {
    1                 rcu_read_unlock();
                      return -EINVAL;
              }
      
  113         {
                      int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
                      u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
                      struct nlattr *cda[ss->cb[cb_id].attr_count + 1];
                      struct nlattr *attr = (void *)nlh + min_len;
                      int attrlen = nlh->nlmsg_len - min_len;
                      __u8 subsys_id = NFNL_SUBSYS_ID(type);
      
                      err = nla_parse(cda, ss->cb[cb_id].attr_count,
                                      attr, attrlen, ss->cb[cb_id].policy);
                      if (err < 0) {
    3                         rcu_read_unlock();
   99                         return err;
                      }
      
  110                 if (nc->call_rcu) {
    7                         err = nc->call_rcu(net, net->nfnl, skb, nlh,
                                                 (const struct nlattr **)cda);
    7                         rcu_read_unlock();
                      } else {
  106                         rcu_read_unlock();
                              nfnl_lock(subsys_id);
  106                         if (nfnl_dereference_protected(subsys_id) != ss ||
  106                             nfnetlink_find_client(type, ss) != nc)
                                      err = -EAGAIN;
  106                         else if (nc->call)
  106                                 err = nc->call(net, net->nfnl, skb, nlh,
                                                     (const struct nlattr **)cda);
                              else
                                      err = -EINVAL;
                              nfnl_unlock(subsys_id);
                      }
   90                 if (err == -EAGAIN)
                              goto replay;
                      return err;
              }
      }
      
      struct nfnl_err {
              struct list_head        head;
              struct nlmsghdr                *nlh;
              int                        err;
      };
      
      static int nfnl_err_add(struct list_head *list, struct nlmsghdr *nlh, int err)
      {
              struct nfnl_err *nfnl_err;
      
              nfnl_err = kmalloc(sizeof(struct nfnl_err), GFP_KERNEL);
              if (nfnl_err == NULL)
                      return -ENOMEM;
      
              nfnl_err->nlh = nlh;
              nfnl_err->err = err;
              list_add_tail(&nfnl_err->head, list);
      
              return 0;
      }
      
      static void nfnl_err_del(struct nfnl_err *nfnl_err)
      {
              list_del(&nfnl_err->head);
              kfree(nfnl_err);
      }
      
      static void nfnl_err_reset(struct list_head *err_list)
      {
              struct nfnl_err *nfnl_err, *next;
      
              list_for_each_entry_safe(nfnl_err, next, err_list, head)
                      nfnl_err_del(nfnl_err);
      }
      
      static void nfnl_err_deliver(struct list_head *err_list, struct sk_buff *skb)
      {
              struct nfnl_err *nfnl_err, *next;
      
              list_for_each_entry_safe(nfnl_err, next, err_list, head) {
                      netlink_ack(skb, nfnl_err->nlh, nfnl_err->err);
                      nfnl_err_del(nfnl_err);
              }
      }
      
      enum {
              NFNL_BATCH_FAILURE        = (1 << 0),
              NFNL_BATCH_DONE                = (1 << 1),
              NFNL_BATCH_REPLAY        = (1 << 2),
      };
      
      static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
                                      u_int16_t subsys_id)
      {
              struct sk_buff *oskb = skb;
    2         struct net *net = sock_net(skb->sk);
              const struct nfnetlink_subsystem *ss;
              const struct nfnl_callback *nc;
              static LIST_HEAD(err_list);
              u32 status;
              int err;
      
              if (subsys_id >= NFNL_SUBSYS_COUNT)
    1                 return netlink_ack(skb, nlh, -EINVAL);
      replay:
              status = 0;
      
    6         skb = netlink_skb_clone(oskb, GFP_KERNEL);
              if (!skb)
                      return netlink_ack(oskb, nlh, -ENOMEM);
      
    6         nfnl_lock(subsys_id);
    6         ss = nfnl_dereference_protected(subsys_id);
              if (!ss) {
      #ifdef CONFIG_MODULES
    6                 nfnl_unlock(subsys_id);
                      request_module("nfnetlink-subsys-%d", subsys_id);
                      nfnl_lock(subsys_id);
    4                 ss = nfnl_dereference_protected(subsys_id);
                      if (!ss)
      #endif
                      {
                              nfnl_unlock(subsys_id);
                              netlink_ack(oskb, nlh, -EOPNOTSUPP);
                              return kfree_skb(skb);
                      }
              }
      
              if (!ss->commit || !ss->abort) {
    4                 nfnl_unlock(subsys_id);
                      netlink_ack(oskb, nlh, -EOPNOTSUPP);
                      return kfree_skb(skb);
              }
      
              while (skb->len >= nlmsg_total_size(0)) {
                      int msglen, type;
      
                      nlh = nlmsg_hdr(skb);
                      err = 0;
      
                      if (nlh->nlmsg_len < NLMSG_HDRLEN ||
                          skb->len < nlh->nlmsg_len ||
                          nlmsg_len(nlh) < sizeof(struct nfgenmsg)) {
                              nfnl_err_reset(&err_list);
                              status |= NFNL_BATCH_FAILURE;
                              goto done;
                      }
      
                      /* Only requests are handled by the kernel */
                      if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
                              err = -EINVAL;
                              goto ack;
                      }
      
                      type = nlh->nlmsg_type;
                      if (type == NFNL_MSG_BATCH_BEGIN) {
                              /* Malformed: Batch begin twice */
                              nfnl_err_reset(&err_list);
                              status |= NFNL_BATCH_FAILURE;
                              goto done;
                      } else if (type == NFNL_MSG_BATCH_END) {
                              status |= NFNL_BATCH_DONE;
                              goto done;
                      } else if (type < NLMSG_MIN_TYPE) {
                              err = -EINVAL;
                              goto ack;
                      }
      
                      /* We only accept a batch with messages for the same
                       * subsystem.
                       */
                      if (NFNL_SUBSYS_ID(type) != subsys_id) {
                              err = -EINVAL;
                              goto ack;
                      }
      
                      nc = nfnetlink_find_client(type, ss);
                      if (!nc) {
                              err = -EINVAL;
                              goto ack;
                      }
      
                      {
                              int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
                              u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
                              struct nlattr *cda[ss->cb[cb_id].attr_count + 1];
                              struct nlattr *attr = (void *)nlh + min_len;
                              int attrlen = nlh->nlmsg_len - min_len;
      
                              err = nla_parse(cda, ss->cb[cb_id].attr_count,
                                              attr, attrlen, ss->cb[cb_id].policy);
                              if (err < 0)
                                      goto ack;
      
                              if (nc->call_batch) {
                                      err = nc->call_batch(net, net->nfnl, skb, nlh,
                                                           (const struct nlattr **)cda);
                              }
      
                              /* The lock was released to autoload some module, we
                               * have to abort and start from scratch using the
                               * original skb.
                               */
                              if (err == -EAGAIN) {
                                      status |= NFNL_BATCH_REPLAY;
                                      goto next;
                              }
                      }
      ack:
                      if (nlh->nlmsg_flags & NLM_F_ACK || err) {
                              /* Errors are delivered once the full batch has been
                               * processed, this avoids that the same error is
                               * reported several times when replaying the batch.
                               */
                              if (nfnl_err_add(&err_list, nlh, err) < 0) {
                                      /* We failed to enqueue an error, reset the
                                       * list of errors and send OOM to userspace
                                       * pointing to the batch header.
                                       */
                                      nfnl_err_reset(&err_list);
                                      netlink_ack(oskb, nlmsg_hdr(oskb), -ENOMEM);
                                      status |= NFNL_BATCH_FAILURE;
                                      goto done;
                              }
                              /* We don't stop processing the batch on errors, thus,
                               * userspace gets all the errors that the batch
                               * triggers.
                               */
                              if (err)
                                      status |= NFNL_BATCH_FAILURE;
                      }
      next:
                      msglen = NLMSG_ALIGN(nlh->nlmsg_len);
                      if (msglen > skb->len)
                              msglen = skb->len;
                      skb_pull(skb, msglen);
              }
      done:
              if (status & NFNL_BATCH_REPLAY) {
                      ss->abort(net, oskb);
                      nfnl_err_reset(&err_list);
                      nfnl_unlock(subsys_id);
                      kfree_skb(skb);
                      goto replay;
              } else if (status == NFNL_BATCH_DONE) {
                      ss->commit(net, oskb);
              } else {
                      ss->abort(net, oskb);
              }
      
              nfnl_err_deliver(&err_list, oskb);
              nfnl_unlock(subsys_id);
              kfree_skb(skb);
      }
      
      static void nfnetlink_rcv(struct sk_buff *skb)
      {
  130         struct nlmsghdr *nlh = nlmsg_hdr(skb);
              u_int16_t res_id;
              int msglen;
      
  105         if (nlh->nlmsg_len < NLMSG_HDRLEN ||
  130             skb->len < nlh->nlmsg_len)
                      return;
      
  128         if (!netlink_net_capable(skb, CAP_NET_ADMIN)) {
    2                 netlink_ack(skb, nlh, -EPERM);
                      return;
              }
      
  126         if (nlh->nlmsg_type == NFNL_MSG_BATCH_BEGIN) {
                      struct nfgenmsg *nfgenmsg;
      
    7                 msglen = NLMSG_ALIGN(nlh->nlmsg_len);
                      if (msglen > skb->len)
    2                         msglen = skb->len;
      
    7                 if (nlh->nlmsg_len < NLMSG_HDRLEN ||
                          skb->len < NLMSG_HDRLEN + sizeof(struct nfgenmsg))
                              return;
      
                      nfgenmsg = nlmsg_data(nlh);
    7                 skb_pull(skb, msglen);
                      /* Work around old nft using host byte order */
                      if (nfgenmsg->res_id == NFNL_SUBSYS_NFTABLES)
                              res_id = NFNL_SUBSYS_NFTABLES;
                      else
    5                         res_id = ntohs(nfgenmsg->res_id);
    7                 nfnetlink_rcv_batch(skb, nlh, res_id);
              } else {
  119                 netlink_rcv_skb(skb, &nfnetlink_rcv_msg);
              }
      }
      
      #ifdef CONFIG_MODULES
    5 static int nfnetlink_bind(struct net *net, int group)
      {
              const struct nfnetlink_subsystem *ss;
              int type;
      
    6         if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
                      return 0;
      
    5         type = nfnl_group2type[group];
      
    5         rcu_read_lock();
    5         ss = nfnetlink_get_subsys(type << 8);
    5         rcu_read_unlock();
              if (!ss)
    5                 request_module_nowait("nfnetlink-subsys-%d", type);
              return 0;
      }
      #endif
      
      static int __net_init nfnetlink_net_init(struct net *net)
      {
              struct sock *nfnl;
  109         struct netlink_kernel_cfg cfg = {
                      .groups        = NFNLGRP_MAX,
                      .input        = nfnetlink_rcv,
      #ifdef CONFIG_MODULES
                      .bind        = nfnetlink_bind,
      #endif
              };
      
              nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, &cfg);
              if (!nfnl)
                      return -ENOMEM;
  109         net->nfnl_stash = nfnl;
              rcu_assign_pointer(net->nfnl, nfnl);
  109         return 0;
      }
      
      static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list)
      {
              struct net *net;
      
              list_for_each_entry(net, net_exit_list, exit_list)
                      RCU_INIT_POINTER(net->nfnl, NULL);
              synchronize_net();
              list_for_each_entry(net, net_exit_list, exit_list)
                      netlink_kernel_release(net->nfnl_stash);
      }
      
      static struct pernet_operations nfnetlink_net_ops = {
              .init                = nfnetlink_net_init,
              .exit_batch        = nfnetlink_net_exit_batch,
      };
      
      static int __init nfnetlink_init(void)
      {
              int i;
      
              for (i = NFNLGRP_NONE + 1; i <= NFNLGRP_MAX; i++)
                      BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE);
      
              for (i=0; i<NFNL_SUBSYS_COUNT; i++)
                      mutex_init(&table[i].mutex);
      
              pr_info("Netfilter messages via NETLINK v%s.\n", nfversion);
              return register_pernet_subsys(&nfnetlink_net_ops);
      }
      
      static void __exit nfnetlink_exit(void)
      {
              pr_info("Removing netfilter NETLINK layer.\n");
              unregister_pernet_subsys(&nfnetlink_net_ops);
      }
      module_init(nfnetlink_init);
      module_exit(nfnetlink_exit);
      /*
       * x_tables core - Backend for {ip,ip6,arp}_tables
       *
       * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
       * Copyright (C) 2006-2012 Patrick McHardy <kaber@trash.net>
       *
       * Based on existing ip_tables code which is
       *   Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
       *   Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
       *
       * This program is free software; you can redistribute it and/or modify
       * it under the terms of the GNU General Public License version 2 as
       * published by the Free Software Foundation.
       *
       */
      #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      #include <linux/kernel.h>
      #include <linux/module.h>
      #include <linux/socket.h>
      #include <linux/net.h>
      #include <linux/proc_fs.h>
      #include <linux/seq_file.h>
      #include <linux/string.h>
      #include <linux/vmalloc.h>
      #include <linux/mutex.h>
      #include <linux/mm.h>
      #include <linux/slab.h>
      #include <linux/audit.h>
      #include <linux/user_namespace.h>
      #include <net/net_namespace.h>
      
      #include <linux/netfilter/x_tables.h>
      #include <linux/netfilter_arp.h>
      #include <linux/netfilter_ipv4/ip_tables.h>
      #include <linux/netfilter_ipv6/ip6_tables.h>
      #include <linux/netfilter_arp/arp_tables.h>
      
      MODULE_LICENSE("GPL");
      MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
      MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
      
      #define XT_PCPU_BLOCK_SIZE 4096
      
      struct compat_delta {
              unsigned int offset; /* offset in kernel */
              int delta; /* delta in 32bit user land */
      };
      
      struct xt_af {
              struct mutex mutex;
              struct list_head match;
              struct list_head target;
      #ifdef CONFIG_COMPAT
              struct mutex compat_mutex;
              struct compat_delta *compat_tab;
              unsigned int number; /* number of slots in compat_tab[] */
              unsigned int cur; /* number of used slots in compat_tab[] */
      #endif
      };
      
      static struct xt_af *xt;
      
      static const char *const xt_prefix[NFPROTO_NUMPROTO] = {
              [NFPROTO_UNSPEC] = "x",
              [NFPROTO_IPV4]   = "ip",
              [NFPROTO_ARP]    = "arp",