// SPDX-License-Identifier: GPL-2.0
      /*
       * bsg.c - block layer implementation of the sg v4 interface
       */
      #include <linux/module.h>
      #include <linux/init.h>
      #include <linux/file.h>
      #include <linux/blkdev.h>
      #include <linux/cdev.h>
      #include <linux/jiffies.h>
      #include <linux/percpu.h>
      #include <linux/idr.h>
      #include <linux/bsg.h>
      #include <linux/slab.h>
      
      #include <scsi/scsi.h>
      #include <scsi/scsi_ioctl.h>
      #include <scsi/scsi_cmnd.h>
      #include <scsi/scsi_device.h>
      #include <scsi/scsi_driver.h>
      #include <scsi/sg.h>
      
      #define BSG_DESCRIPTION        "Block layer SCSI generic (bsg) driver"
      #define BSG_VERSION        "0.4"
      
      #define bsg_dbg(bd, fmt, ...) \
              pr_debug("%s: " fmt, (bd)->name, ##__VA_ARGS__)
      
      struct bsg_device {
              struct request_queue *queue;
              spinlock_t lock;
              struct hlist_node dev_list;
              refcount_t ref_count;
              char name[20];
              int max_queue;
      };
      
      #define BSG_DEFAULT_CMDS        64
      #define BSG_MAX_DEVS                32768
      
      static DEFINE_MUTEX(bsg_mutex);
      static DEFINE_IDR(bsg_minor_idr);
      
      #define BSG_LIST_ARRAY_SIZE        8
      static struct hlist_head bsg_device_list[BSG_LIST_ARRAY_SIZE];
      
      static struct class *bsg_class;
      static int bsg_major;
      
      static inline struct hlist_head *bsg_dev_idx_hash(int index)
      {
              return &bsg_device_list[index & (BSG_LIST_ARRAY_SIZE - 1)];
      }
      
      #define uptr64(val) ((void __user *)(uintptr_t)(val))
      
      static int bsg_scsi_check_proto(struct sg_io_v4 *hdr)
      {
              if (hdr->protocol != BSG_PROTOCOL_SCSI  ||
                  hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_CMD)
                      return -EINVAL;
              return 0;
      }
      
      static int bsg_scsi_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
                      fmode_t mode)
      {
              struct scsi_request *sreq = scsi_req(rq);
      
              if (hdr->dout_xfer_len && hdr->din_xfer_len) {
                      pr_warn_once("BIDI support in bsg has been removed.\n");
                      return -EOPNOTSUPP;
              }
      
              sreq->cmd_len = hdr->request_len;
              if (sreq->cmd_len > BLK_MAX_CDB) {
                      sreq->cmd = kzalloc(sreq->cmd_len, GFP_KERNEL);
                      if (!sreq->cmd)
                              return -ENOMEM;
              }
      
              if (copy_from_user(sreq->cmd, uptr64(hdr->request), sreq->cmd_len))
                      return -EFAULT;
              if (blk_verify_command(sreq->cmd, mode))
                      return -EPERM;
              return 0;
      }
      
      static int bsg_scsi_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
      {
              struct scsi_request *sreq = scsi_req(rq);
              int ret = 0;
      
              /*
               * fill in all the output members
               */
              hdr->device_status = sreq->result & 0xff;
              hdr->transport_status = host_byte(sreq->result);
              hdr->driver_status = driver_byte(sreq->result);
              hdr->info = 0;
              if (hdr->device_status || hdr->transport_status || hdr->driver_status)
                      hdr->info |= SG_INFO_CHECK;
              hdr->response_len = 0;
      
              if (sreq->sense_len && hdr->response) {
                      int len = min_t(unsigned int, hdr->max_response_len,
                                              sreq->sense_len);
      
                      if (copy_to_user(uptr64(hdr->response), sreq->sense, len))
                              ret = -EFAULT;
                      else
                              hdr->response_len = len;
              }
      
              if (rq_data_dir(rq) == READ)
                      hdr->din_resid = sreq->resid_len;
              else
                      hdr->dout_resid = sreq->resid_len;
      
              return ret;
      }
      
      static void bsg_scsi_free_rq(struct request *rq)
      {
              scsi_req_free_cmd(scsi_req(rq));
      }
      
      static const struct bsg_ops bsg_scsi_ops = {
              .check_proto                = bsg_scsi_check_proto,
              .fill_hdr                = bsg_scsi_fill_hdr,
              .complete_rq                = bsg_scsi_complete_rq,
              .free_rq                = bsg_scsi_free_rq,
      };
      
      static int bsg_sg_io(struct request_queue *q, fmode_t mode, void __user *uarg)
      {
              struct request *rq;
              struct bio *bio;
              struct sg_io_v4 hdr;
              int ret;
      
              if (copy_from_user(&hdr, uarg, sizeof(hdr)))
                      return -EFAULT;
      
              if (!q->bsg_dev.class_dev)
                      return -ENXIO;
      
              if (hdr.guard != 'Q')
                      return -EINVAL;
              ret = q->bsg_dev.ops->check_proto(&hdr);
              if (ret)
                      return ret;
      
              rq = blk_get_request(q, hdr.dout_xfer_len ?
                              REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, 0);
              if (IS_ERR(rq))
                      return PTR_ERR(rq);
      
              ret = q->bsg_dev.ops->fill_hdr(rq, &hdr, mode);
              if (ret)
                      return ret;
      
              rq->timeout = msecs_to_jiffies(hdr.timeout);
              if (!rq->timeout)
                      rq->timeout = q->sg_timeout;
              if (!rq->timeout)
                      rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
              if (rq->timeout < BLK_MIN_SG_TIMEOUT)
                      rq->timeout = BLK_MIN_SG_TIMEOUT;
      
              if (hdr.dout_xfer_len) {
                      ret = blk_rq_map_user(q, rq, NULL, uptr64(hdr.dout_xferp),
                                      hdr.dout_xfer_len, GFP_KERNEL);
              } else if (hdr.din_xfer_len) {
                      ret = blk_rq_map_user(q, rq, NULL, uptr64(hdr.din_xferp),
                                      hdr.din_xfer_len, GFP_KERNEL);
              }
      
              if (ret)
                      goto out_free_rq;
      
              bio = rq->bio;
      
              blk_execute_rq(q, NULL, rq, !(hdr.flags & BSG_FLAG_Q_AT_TAIL));
              ret = rq->q->bsg_dev.ops->complete_rq(rq, &hdr);
              blk_rq_unmap_user(bio);
      
      out_free_rq:
              rq->q->bsg_dev.ops->free_rq(rq);
              blk_put_request(rq);
              if (!ret && copy_to_user(uarg, &hdr, sizeof(hdr)))
                      return -EFAULT;
              return ret;
      }
      
      static struct bsg_device *bsg_alloc_device(void)
      {
              struct bsg_device *bd;
      
              bd = kzalloc(sizeof(struct bsg_device), GFP_KERNEL);
              if (unlikely(!bd))
                      return NULL;
      
              spin_lock_init(&bd->lock);
              bd->max_queue = BSG_DEFAULT_CMDS;
              INIT_HLIST_NODE(&bd->dev_list);
              return bd;
      }
      
      static int bsg_put_device(struct bsg_device *bd)
      {
              struct request_queue *q = bd->queue;
      
              mutex_lock(&bsg_mutex);
      
              if (!refcount_dec_and_test(&bd->ref_count)) {
                      mutex_unlock(&bsg_mutex);
                      return 0;
              }
      
              hlist_del(&bd->dev_list);
              mutex_unlock(&bsg_mutex);
      
              bsg_dbg(bd, "tearing down\n");
      
              /*
               * close can always block
               */
              kfree(bd);
              blk_put_queue(q);
              return 0;
      }
      
      static struct bsg_device *bsg_add_device(struct inode *inode,
                                               struct request_queue *rq,
                                               struct file *file)
      {
              struct bsg_device *bd;
              unsigned char buf[32];
      
              lockdep_assert_held(&bsg_mutex);
      
              if (!blk_get_queue(rq))
                      return ERR_PTR(-ENXIO);
      
              bd = bsg_alloc_device();
              if (!bd) {
                      blk_put_queue(rq);
                      return ERR_PTR(-ENOMEM);
              }
      
              bd->queue = rq;
      
              refcount_set(&bd->ref_count, 1);
              hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(iminor(inode)));
      
              strncpy(bd->name, dev_name(rq->bsg_dev.class_dev), sizeof(bd->name) - 1);
              bsg_dbg(bd, "bound to <%s>, max queue %d\n",
                      format_dev_t(buf, inode->i_rdev), bd->max_queue);
      
              return bd;
      }
      
      static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q)
      {
              struct bsg_device *bd;
      
              lockdep_assert_held(&bsg_mutex);
      
              hlist_for_each_entry(bd, bsg_dev_idx_hash(minor), dev_list) {
                      if (bd->queue == q) {
                              refcount_inc(&bd->ref_count);
                              goto found;
                      }
              }
              bd = NULL;
      found:
              return bd;
      }
      
      static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
      {
              struct bsg_device *bd;
              struct bsg_class_device *bcd;
      
              /*
               * find the class device
               */
              mutex_lock(&bsg_mutex);
              bcd = idr_find(&bsg_minor_idr, iminor(inode));
      
              if (!bcd) {
                      bd = ERR_PTR(-ENODEV);
                      goto out_unlock;
              }
      
              bd = __bsg_get_device(iminor(inode), bcd->queue);
              if (!bd)
                      bd = bsg_add_device(inode, bcd->queue, file);
      
      out_unlock:
              mutex_unlock(&bsg_mutex);
              return bd;
      }
      
      static int bsg_open(struct inode *inode, struct file *file)
      {
              struct bsg_device *bd;
      
              bd = bsg_get_device(inode, file);
      
              if (IS_ERR(bd))
                      return PTR_ERR(bd);
      
              file->private_data = bd;
              return 0;
      }
      
      static int bsg_release(struct inode *inode, struct file *file)
      {
              struct bsg_device *bd = file->private_data;
      
              file->private_data = NULL;
              return bsg_put_device(bd);
      }
      
      static int bsg_get_command_q(struct bsg_device *bd, int __user *uarg)
      {
              return put_user(bd->max_queue, uarg);
      }
      
      static int bsg_set_command_q(struct bsg_device *bd, int __user *uarg)
      {
              int queue;
      
              if (get_user(queue, uarg))
                      return -EFAULT;
              if (queue < 1)
                      return -EINVAL;
      
              spin_lock_irq(&bd->lock);
              bd->max_queue = queue;
              spin_unlock_irq(&bd->lock);
              return 0;
      }
      
      static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
      {
              struct bsg_device *bd = file->private_data;
              void __user *uarg = (void __user *) arg;
      
              switch (cmd) {
              /*
               * Our own ioctls
               */
              case SG_GET_COMMAND_Q:
                      return bsg_get_command_q(bd, uarg);
              case SG_SET_COMMAND_Q:
                      return bsg_set_command_q(bd, uarg);
      
              /*
               * SCSI/sg ioctls
               */
              case SG_GET_VERSION_NUM:
              case SCSI_IOCTL_GET_IDLUN:
              case SCSI_IOCTL_GET_BUS_NUMBER:
              case SG_SET_TIMEOUT:
              case SG_GET_TIMEOUT:
              case SG_GET_RESERVED_SIZE:
              case SG_SET_RESERVED_SIZE:
              case SG_EMULATED_HOST:
              case SCSI_IOCTL_SEND_COMMAND:
                      return scsi_cmd_ioctl(bd->queue, NULL, file->f_mode, cmd, uarg);
              case SG_IO:
                      return bsg_sg_io(bd->queue, file->f_mode, uarg);
              default:
                      return -ENOTTY;
              }
      }
      
      static const struct file_operations bsg_fops = {
              .open                =        bsg_open,
              .release        =        bsg_release,
              .unlocked_ioctl        =        bsg_ioctl,
              .owner                =        THIS_MODULE,
              .llseek                =        default_llseek,
      };
      
   24 void bsg_unregister_queue(struct request_queue *q)
      {
              struct bsg_class_device *bcd = &q->bsg_dev;
      
   24         if (!bcd->class_dev)
                      return;
      
   24         mutex_lock(&bsg_mutex);
              idr_remove(&bsg_minor_idr, bcd->minor);
              if (q->kobj.sd)
    5                 sysfs_remove_link(&q->kobj, "bsg");
   24         device_unregister(bcd->class_dev);
              bcd->class_dev = NULL;
              mutex_unlock(&bsg_mutex);
      }
      EXPORT_SYMBOL_GPL(bsg_unregister_queue);
      
      int bsg_register_queue(struct request_queue *q, struct device *parent,
                      const char *name, const struct bsg_ops *ops)
      {
              struct bsg_class_device *bcd;
              dev_t dev;
              int ret;
              struct device *class_dev = NULL;
      
              /*
               * we need a proper transport to send commands, not a stacked device
               */
              if (!queue_is_mq(q))
                      return 0;
      
              bcd = &q->bsg_dev;
              memset(bcd, 0, sizeof(*bcd));
      
              mutex_lock(&bsg_mutex);
      
              ret = idr_alloc(&bsg_minor_idr, bcd, 0, BSG_MAX_DEVS, GFP_KERNEL);
              if (ret < 0) {
                      if (ret == -ENOSPC) {
                              printk(KERN_ERR "bsg: too many bsg devices\n");
                              ret = -EINVAL;
                      }
                      goto unlock;
              }
      
              bcd->minor = ret;
              bcd->queue = q;
              bcd->ops = ops;
              dev = MKDEV(bsg_major, bcd->minor);
              class_dev = device_create(bsg_class, parent, dev, NULL, "%s", name);
              if (IS_ERR(class_dev)) {
                      ret = PTR_ERR(class_dev);
                      goto idr_remove;
              }
              bcd->class_dev = class_dev;
      
              if (q->kobj.sd) {
                      ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg");
                      if (ret)
                              goto unregister_class_dev;
              }
      
              mutex_unlock(&bsg_mutex);
              return 0;
      
      unregister_class_dev:
              device_unregister(class_dev);
      idr_remove:
              idr_remove(&bsg_minor_idr, bcd->minor);
      unlock:
              mutex_unlock(&bsg_mutex);
              return ret;
      }
      
      int bsg_scsi_register_queue(struct request_queue *q, struct device *parent)
      {
              if (!blk_queue_scsi_passthrough(q)) {
                      WARN_ONCE(true, "Attempt to register a non-SCSI queue\n");
                      return -EINVAL;
              }
      
              return bsg_register_queue(q, parent, dev_name(parent), &bsg_scsi_ops);
      }
      EXPORT_SYMBOL_GPL(bsg_scsi_register_queue);
      
      static struct cdev bsg_cdev;
      
      static char *bsg_devnode(struct device *dev, umode_t *mode)
      {
   24         return kasprintf(GFP_KERNEL, "bsg/%s", dev_name(dev));
      }
      
      static int __init bsg_init(void)
      {
              int ret, i;
              dev_t devid;
      
              for (i = 0; i < BSG_LIST_ARRAY_SIZE; i++)
                      INIT_HLIST_HEAD(&bsg_device_list[i]);
      
              bsg_class = class_create(THIS_MODULE, "bsg");
              if (IS_ERR(bsg_class))
                      return PTR_ERR(bsg_class);
              bsg_class->devnode = bsg_devnode;
      
              ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg");
              if (ret)
                      goto destroy_bsg_class;
      
              bsg_major = MAJOR(devid);
      
              cdev_init(&bsg_cdev, &bsg_fops);
              ret = cdev_add(&bsg_cdev, MKDEV(bsg_major, 0), BSG_MAX_DEVS);
              if (ret)
                      goto unregister_chrdev;
      
              printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION
                     " loaded (major %d)\n", bsg_major);
              return 0;
      unregister_chrdev:
              unregister_chrdev_region(MKDEV(bsg_major, 0), BSG_MAX_DEVS);
      destroy_bsg_class:
              class_destroy(bsg_class);
              return ret;
      }
      
      MODULE_AUTHOR("Jens Axboe");
      MODULE_DESCRIPTION(BSG_DESCRIPTION);
      MODULE_LICENSE("GPL");
      
      device_initcall(bsg_init);
      // SPDX-License-Identifier: GPL-2.0-only
      /*
       *  linux/kernel/exit.c
       *
       *  Copyright (C) 1991, 1992  Linus Torvalds
       */
      
      #include <linux/mm.h>
      #include <linux/slab.h>
      #include <linux/sched/autogroup.h>
      #include <linux/sched/mm.h>
      #include <linux/sched/stat.h>
      #include <linux/sched/task.h>
      #include <linux/sched/task_stack.h>
      #include <linux/sched/cputime.h>
      #include <linux/interrupt.h>
      #include <linux/module.h>
      #include <linux/capability.h>
      #include <linux/completion.h>
      #include <linux/personality.h>
      #include <linux/tty.h>
      #include <linux/iocontext.h>
      #include <linux/key.h>
      #include <linux/cpu.h>
      #include <linux/acct.h>
      #include <linux/tsacct_kern.h>
      #include <linux/file.h>
      #include <linux/fdtable.h>
      #include <linux/freezer.h>
      #include <linux/binfmts.h>
      #include <linux/nsproxy.h>
      #include <linux/pid_namespace.h>
      #include <linux/ptrace.h>
      #include <linux/profile.h>
      #include <linux/mount.h>
      #include <linux/proc_fs.h>
      #include <linux/kthread.h>
      #include <linux/mempolicy.h>
      #include <linux/taskstats_kern.h>
      #include <linux/delayacct.h>
      #include <linux/cgroup.h>
      #include <linux/syscalls.h>
      #include <linux/signal.h>
      #include <linux/posix-timers.h>
      #include <linux/cn_proc.h>
      #include <linux/mutex.h>
      #include <linux/futex.h>
      #include <linux/pipe_fs_i.h>
      #include <linux/audit.h> /* for audit_free() */
      #include <linux/resource.h>
      #include <linux/blkdev.h>
      #include <linux/task_io_accounting_ops.h>
      #include <linux/tracehook.h>
      #include <linux/fs_struct.h>
      #include <linux/init_task.h>
      #include <linux/perf_event.h>
      #include <trace/events/sched.h>
      #include <linux/hw_breakpoint.h>
      #include <linux/oom.h>
      #include <linux/writeback.h>
      #include <linux/shm.h>
      #include <linux/kcov.h>
      #include <linux/random.h>
      #include <linux/rcuwait.h>
      #include <linux/compat.h>
      
      #include <linux/uaccess.h>
      #include <asm/unistd.h>
      #include <asm/pgtable.h>
      #include <asm/mmu_context.h>
      
      static void __unhash_process(struct task_struct *p, bool group_dead)
      {
              nr_threads--;
              detach_pid(p, PIDTYPE_PID);
              if (group_dead) {
                      detach_pid(p, PIDTYPE_TGID);
                      detach_pid(p, PIDTYPE_PGID);
                      detach_pid(p, PIDTYPE_SID);
      
                      list_del_rcu(&p->tasks);
                      list_del_init(&p->sibling);
                      __this_cpu_dec(process_counts);
              }
              list_del_rcu(&p->thread_group);
              list_del_rcu(&p->thread_node);
      }
      
      /*
       * This function expects the tasklist_lock write-locked.
       */
      static void __exit_signal(struct task_struct *tsk)
      {
              struct signal_struct *sig = tsk->signal;
              bool group_dead = thread_group_leader(tsk);
              struct sighand_struct *sighand;
              struct tty_struct *uninitialized_var(tty);
              u64 utime, stime;
      
              sighand = rcu_dereference_check(tsk->sighand,
                                              lockdep_tasklist_lock_is_held());
              spin_lock(&sighand->siglock);
      
      #ifdef CONFIG_POSIX_TIMERS
              posix_cpu_timers_exit(tsk);
              if (group_dead) {
                      posix_cpu_timers_exit_group(tsk);
              } else {
                      /*
                       * This can only happen if the caller is de_thread().
                       * FIXME: this is the temporary hack, we should teach
                       * posix-cpu-timers to handle this case correctly.
                       */
                      if (unlikely(has_group_leader_pid(tsk)))
                              posix_cpu_timers_exit_group(tsk);
              }
      #endif
      
              if (group_dead) {
                      tty = sig->tty;
                      sig->tty = NULL;
              } else {
                      /*
                       * If there is any task waiting for the group exit
                       * then notify it:
                       */
                      if (sig->notify_count > 0 && !--sig->notify_count)
                              wake_up_process(sig->group_exit_task);
      
                      if (tsk == sig->curr_target)
                              sig->curr_target = next_thread(tsk);
              }
      
              add_device_randomness((const void*) &tsk->se.sum_exec_runtime,
                                    sizeof(unsigned long long));
      
              /*
               * Accumulate here the counters for all threads as they die. We could
               * skip the group leader because it is the last user of signal_struct,
               * but we want to avoid the race with thread_group_cputime() which can
               * see the empty ->thread_head list.
               */
              task_cputime(tsk, &utime, &stime);
              write_seqlock(&sig->stats_lock);
              sig->utime += utime;
              sig->stime += stime;
              sig->gtime += task_gtime(tsk);
              sig->min_flt += tsk->min_flt;
              sig->maj_flt += tsk->maj_flt;
              sig->nvcsw += tsk->nvcsw;
              sig->nivcsw += tsk->nivcsw;
              sig->inblock += task_io_get_inblock(tsk);
              sig->oublock += task_io_get_oublock(tsk);
              task_io_accounting_add(&sig->ioac, &tsk->ioac);
              sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
              sig->nr_threads--;
              __unhash_process(tsk, group_dead);
              write_sequnlock(&sig->stats_lock);
      
              /*
               * Do this under ->siglock, we can race with another thread
               * doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals.
               */
              flush_sigqueue(&tsk->pending);
              tsk->sighand = NULL;
              spin_unlock(&sighand->siglock);
      
              __cleanup_sighand(sighand);
              clear_tsk_thread_flag(tsk, TIF_SIGPENDING);
              if (group_dead) {
                      flush_sigqueue(&sig->shared_pending);
                      tty_kref_put(tty);
              }
      }
      
      static void delayed_put_task_struct(struct rcu_head *rhp)
      {
              struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
      
              perf_event_delayed_put(tsk);
              trace_sched_process_free(tsk);
              put_task_struct(tsk);
      }
      
      void put_task_struct_rcu_user(struct task_struct *task)
      {
  858         if (refcount_dec_and_test(&task->rcu_users))
  468                 call_rcu(&task->rcu, delayed_put_task_struct);
      }
      
      void release_task(struct task_struct *p)
      {
              struct task_struct *leader;
              int zap_leader;
      repeat:
              /* don't need to get the RCU readlock here - the process is dead and
               * can't be modifying its own credentials. But shut RCU-lockdep up */
              rcu_read_lock();
              atomic_dec(&__task_cred(p)->user->processes);
              rcu_read_unlock();
      
              proc_flush_task(p);
              cgroup_release(p);
      
              write_lock_irq(&tasklist_lock);
              ptrace_release_task(p);
              __exit_signal(p);
      
              /*
               * If we are the last non-leader member of the thread
               * group, and the leader is zombie, then notify the
               * group leader's parent process. (if it wants notification.)
               */
              zap_leader = 0;
              leader = p->group_leader;
              if (leader != p && thread_group_empty(leader)
                              && leader->exit_state == EXIT_ZOMBIE) {
                      /*
                       * If we were the last child thread and the leader has
                       * exited already, and the leader's parent ignores SIGCHLD,
                       * then we are the one who should release the leader.
                       */
                      zap_leader = do_notify_parent(leader, leader->exit_signal);
                      if (zap_leader)
                              leader->exit_state = EXIT_DEAD;
              }
      
              write_unlock_irq(&tasklist_lock);
              release_thread(p);
              put_task_struct_rcu_user(p);
      
              p = leader;
              if (unlikely(zap_leader))
                      goto repeat;
      }
      
      void rcuwait_wake_up(struct rcuwait *w)
      {
              struct task_struct *task;
      
              rcu_read_lock();
      
              /*
               * Order condition vs @task, such that everything prior to the load
               * of @task is visible. This is the condition as to why the user called
               * rcuwait_trywake() in the first place. Pairs with set_current_state()
               * barrier (A) in rcuwait_wait_event().
               *
               *    WAIT                WAKE
               *    [S] tsk = current          [S] cond = true
               *        MB (A)              MB (B)
               *    [L] cond                  [L] tsk
               */
              smp_mb(); /* (B) */
      
              task = rcu_dereference(w->task);
              if (task)
                      wake_up_process(task);
              rcu_read_unlock();
      }
      
      /*
       * Determine if a process group is "orphaned", according to the POSIX
       * definition in 2.2.2.52.  Orphaned process groups are not to be affected
       * by terminal-generated stop signals.  Newly orphaned process groups are
       * to receive a SIGHUP and a SIGCONT.
       *
       * "I ask you, have you ever known what it is to be an orphan?"
       */
      static int will_become_orphaned_pgrp(struct pid *pgrp,
                                              struct task_struct *ignored_task)
      {
              struct task_struct *p;
      
              do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
                      if ((p == ignored_task) ||
                          (p->exit_state && thread_group_empty(p)) ||
                          is_global_init(p->real_parent))
                              continue;
      
                      if (task_pgrp(p->real_parent) != pgrp &&
                          task_session(p->real_parent) == task_session(p))
                              return 0;
              } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
      
              return 1;
      }
      
      int is_current_pgrp_orphaned(void)
      {
              int retval;
      
              read_lock(&tasklist_lock);
              retval = will_become_orphaned_pgrp(task_pgrp(current), NULL);
              read_unlock(&tasklist_lock);
      
              return retval;
      }
      
      static bool has_stopped_jobs(struct pid *pgrp)
      {
              struct task_struct *p;
      
              do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
                      if (p->signal->flags & SIGNAL_STOP_STOPPED)
                              return true;
              } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
      
              return false;
      }
      
      /*
       * Check to see if any process groups have become orphaned as
       * a result of our exiting, and if they have any stopped jobs,
       * send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
       */
      static void
      kill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent)
      {
              struct pid *pgrp = task_pgrp(tsk);
              struct task_struct *ignored_task = tsk;
      
              if (!parent)
                      /* exit: our father is in a different pgrp than
                       * we are and we were the only connection outside.
                       */
                      parent = tsk->real_parent;
              else
                      /* reparent: our child is in a different pgrp than
                       * we are, and it was the only connection outside.
                       */
                      ignored_task = NULL;
      
              if (task_pgrp(parent) != pgrp &&
                  task_session(parent) == task_session(tsk) &&
                  will_become_orphaned_pgrp(pgrp, ignored_task) &&
                  has_stopped_jobs(pgrp)) {
                      __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
                      __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
              }
      }
      
      #ifdef CONFIG_MEMCG
      /*
       * A task is exiting.   If it owned this mm, find a new owner for the mm.
       */
      void mm_update_next_owner(struct mm_struct *mm)
      {
              struct task_struct *c, *g, *p = current;
      
      retry:
              /*
               * If the exiting or execing task is not the owner, it's
               * someone else's problem.
               */
              if (mm->owner != p)
                      return;
              /*
               * The current owner is exiting/execing and there are no other
               * candidates.  Do not leave the mm pointing to a possibly
               * freed task structure.
               */
              if (atomic_read(&mm->mm_users) <= 1) {
                      WRITE_ONCE(mm->owner, NULL);
                      return;
              }
      
              read_lock(&tasklist_lock);
              /*
               * Search in the children
               */
              list_for_each_entry(c, &p->children, sibling) {
                      if (c->mm == mm)
                              goto assign_new_owner;
              }
      
              /*
               * Search in the siblings
               */
              list_for_each_entry(c, &p->real_parent->children, sibling) {
                      if (c->mm == mm)
                              goto assign_new_owner;
              }
      
              /*
               * Search through everything else, we should not get here often.
               */
              for_each_process(g) {
                      if (g->flags & PF_KTHREAD)
                              continue;
                      for_each_thread(g, c) {
                              if (c->mm == mm)
                                      goto assign_new_owner;
                              if (c->mm)
                                      break;
                      }
              }
              read_unlock(&tasklist_lock);
              /*
               * We found no owner yet mm_users > 1: this implies that we are
               * most likely racing with swapoff (try_to_unuse()) or /proc or
               * ptrace or page migration (get_task_mm()).  Mark owner as NULL.
               */
              WRITE_ONCE(mm->owner, NULL);
              return;
      
      assign_new_owner:
              BUG_ON(c == p);
              get_task_struct(c);
              /*
               * The task_lock protects c->mm from changing.
               * We always want mm->owner->mm == mm
               */
              task_lock(c);
              /*
               * Delay read_unlock() till we have the task_lock()
               * to ensure that c does not slip away underneath us
               */
              read_unlock(&tasklist_lock);
              if (c->mm != mm) {
                      task_unlock(c);
                      put_task_struct(c);
                      goto retry;
              }
              WRITE_ONCE(mm->owner, c);
              task_unlock(c);
              put_task_struct(c);
      }
      #endif /* CONFIG_MEMCG */
      
      /*
       * Turn us into a lazy TLB process if we
       * aren't already..
       */
      static void exit_mm(void)
      {
              struct mm_struct *mm = current->mm;
              struct core_state *core_state;
      
              mm_release(current, mm);
              if (!mm)
                      return;
              sync_mm_rss(mm);
              /*
               * Serialize with any possible pending coredump.
               * We must hold mmap_sem around checking core_state
               * and clearing tsk->mm.  The core-inducing thread
               * will increment ->nr_threads for each thread in the
               * group with ->mm != NULL.
               */
              down_read(&mm->mmap_sem);
              core_state = mm->core_state;
              if (core_state) {
                      struct core_thread self;
      
                      up_read(&mm->mmap_sem);
      
                      self.task = current;
                      self.next = xchg(&core_state->dumper.next, &self);
                      /*
                       * Implies mb(), the result of xchg() must be visible
                       * to core_state->dumper.
                       */
                      if (atomic_dec_and_test(&core_state->nr_threads))
                              complete(&core_state->startup);
      
                      for (;;) {
                              set_current_state(TASK_UNINTERRUPTIBLE);
                              if (!self.task) /* see coredump_finish() */
                                      break;
                              freezable_schedule();
                      }
                      __set_current_state(TASK_RUNNING);
                      down_read(&mm->mmap_sem);
              }
              mmgrab(mm);
              BUG_ON(mm != current->active_mm);
              /* more a memory barrier than a real lock */
              task_lock(current);
              current->mm = NULL;
              up_read(&mm->mmap_sem);
              enter_lazy_tlb(mm, current);
              task_unlock(current);
              mm_update_next_owner(mm);
              mmput(mm);
              if (test_thread_flag(TIF_MEMDIE))
                      exit_oom_victim();
      }
      
      static struct task_struct *find_alive_thread(struct task_struct *p)
      {
              struct task_struct *t;
      
              for_each_thread(p, t) {
                      if (!(t->flags & PF_EXITING))
                              return t;
              }
              return NULL;
      }
      
      static struct task_struct *find_child_reaper(struct task_struct *father,
                                                      struct list_head *dead)
              __releases(&tasklist_lock)
              __acquires(&tasklist_lock)
      {
              struct pid_namespace *pid_ns = task_active_pid_ns(father);
              struct task_struct *reaper = pid_ns->child_reaper;
              struct task_struct *p, *n;
      
              if (likely(reaper != father))
                      return reaper;
      
              reaper = find_alive_thread(father);
              if (reaper) {
                      pid_ns->child_reaper = reaper;
                      return reaper;
              }
      
              write_unlock_irq(&tasklist_lock);
              if (unlikely(pid_ns == &init_pid_ns)) {
                      panic("Attempted to kill init! exitcode=0x%08x\n",
                              father->signal->group_exit_code ?: father->exit_code);
              }
      
              list_for_each_entry_safe(p, n, dead, ptrace_entry) {
                      list_del_init(&p->ptrace_entry);
                      release_task(p);
              }
      
              zap_pid_ns_processes(pid_ns);
              write_lock_irq(&tasklist_lock);
      
              return father;
      }
      
      /*
       * When we die, we re-parent all our children, and try to:
       * 1. give them to another thread in our thread group, if such a member exists
       * 2. give it to the first ancestor process which prctl'd itself as a
       *    child_subreaper for its children (like a service manager)
       * 3. give it to the init process (PID 1) in our pid namespace
       */
      static struct task_struct *find_new_reaper(struct task_struct *father,
                                                 struct task_struct *child_reaper)
      {
              struct task_struct *thread, *reaper;
      
              thread = find_alive_thread(father);
              if (thread)
                      return thread;
      
              if (father->signal->has_child_subreaper) {
                      unsigned int ns_level = task_pid(father)->level;
                      /*
                       * Find the first ->is_child_subreaper ancestor in our pid_ns.
                       * We can't check reaper != child_reaper to ensure we do not
                       * cross the namespaces, the exiting parent could be injected
                       * by setns() + fork().
                       * We check pid->level, this is slightly more efficient than
                       * task_active_pid_ns(reaper) != task_active_pid_ns(father).
                       */
                      for (reaper = father->real_parent;
                           task_pid(reaper)->level == ns_level;
                           reaper = reaper->real_parent) {
                              if (reaper == &init_task)
                                      break;
                              if (!reaper->signal->is_child_subreaper)
                                      continue;
                              thread = find_alive_thread(reaper);
                              if (thread)
                                      return thread;
                      }
              }
      
              return child_reaper;
      }
      
      /*
      * Any that need to be release_task'd are put on the @dead list.
       */
      static void reparent_leader(struct task_struct *father, struct task_struct *p,
                                      struct list_head *dead)
      {
              if (unlikely(p->exit_state == EXIT_DEAD))
                      return;
      
              /* We don't want people slaying init. */
              p->exit_signal = SIGCHLD;
      
              /* If it has exited notify the new parent about this child's death. */
              if (!p->ptrace &&
                  p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) {
                      if (do_notify_parent(p, p->exit_signal)) {
                              p->exit_state = EXIT_DEAD;
                              list_add(&p->ptrace_entry, dead);
                      }
              }
      
              kill_orphaned_pgrp(p, father);
      }
      
      /*
       * This does two things:
       *
       * A.  Make init inherit all the child processes
       * B.  Check to see if any process groups have become orphaned
       *        as a result of our exiting, and if they have any stopped
       *        jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)
       */
      static void forget_original_parent(struct task_struct *father,
                                              struct list_head *dead)
      {
              struct task_struct *p, *t, *reaper;
      
              if (unlikely(!list_empty(&father->ptraced)))
                      exit_ptrace(father, dead);
      
              /* Can drop and reacquire tasklist_lock */
              reaper = find_child_reaper(father, dead);
              if (list_empty(&father->children))
                      return;
      
              reaper = find_new_reaper(father, reaper);
              list_for_each_entry(p, &father->children, sibling) {
                      for_each_thread(p, t) {
                              t->real_parent = reaper;
                              BUG_ON((!t->ptrace) != (t->parent == father));
                              if (likely(!t->ptrace))
                                      t->parent = t->real_parent;
                              if (t->pdeath_signal)
                                      group_send_sig_info(t->pdeath_signal,
                                                          SEND_SIG_NOINFO, t,
                                                          PIDTYPE_TGID);
                      }
                      /*
                       * If this is a threaded reparent there is no need to
                       * notify anyone anything has happened.
                       */
                      if (!same_thread_group(reaper, father))
                              reparent_leader(father, p, dead);
              }
              list_splice_tail_init(&father->children, &reaper->children);
      }
      
      /*
       * Send signals to all our closest relatives so that they know
       * to properly mourn us..
       */
      static void exit_notify(struct task_struct *tsk, int group_dead)
      {
              bool autoreap;
              struct task_struct *p, *n;
              LIST_HEAD(dead);
      
              write_lock_irq(&tasklist_lock);
              forget_original_parent(tsk, &dead);
      
              if (group_dead)
                      kill_orphaned_pgrp(tsk->group_leader, NULL);
      
              tsk->exit_state = EXIT_ZOMBIE;
              if (unlikely(tsk->ptrace)) {
                      int sig = thread_group_leader(tsk) &&
                                      thread_group_empty(tsk) &&
                                      !ptrace_reparented(tsk) ?
                              tsk->exit_signal : SIGCHLD;
                      autoreap = do_notify_parent(tsk, sig);
              } else if (thread_group_leader(tsk)) {
                      autoreap = thread_group_empty(tsk) &&
                              do_notify_parent(tsk, tsk->exit_signal);
              } else {
                      autoreap = true;
              }
      
              if (autoreap) {
                      tsk->exit_state = EXIT_DEAD;
                      list_add(&tsk->ptrace_entry, &dead);
              }
      
              /* mt-exec, de_thread() is waiting for group leader */
              if (unlikely(tsk->signal->notify_count < 0))
                      wake_up_process(tsk->signal->group_exit_task);
              write_unlock_irq(&tasklist_lock);
      
              list_for_each_entry_safe(p, n, &dead, ptrace_entry) {
                      list_del_init(&p->ptrace_entry);
                      release_task(p);
              }
      }
      
      #ifdef CONFIG_DEBUG_STACK_USAGE
      static void check_stack_usage(void)
      {
              static DEFINE_SPINLOCK(low_water_lock);
              static int lowest_to_date = THREAD_SIZE;
              unsigned long free;
      
              free = stack_not_used(current);
      
              if (free >= lowest_to_date)
                      return;
      
              spin_lock(&low_water_lock);
              if (free < lowest_to_date) {
                      pr_info("%s (%d) used greatest stack depth: %lu bytes left\n",
                              current->comm, task_pid_nr(current), free);
                      lowest_to_date = free;
              }
              spin_unlock(&low_water_lock);
      }
      #else
      static inline void check_stack_usage(void) {}
      #endif
      
      void __noreturn do_exit(long code)
      {
              struct task_struct *tsk = current;
              int group_dead;
      
              profile_task_exit(tsk);
              kcov_task_exit(tsk);
      
              WARN_ON(blk_needs_flush_plug(tsk));
      
              if (unlikely(in_interrupt()))
                      panic("Aiee, killing interrupt handler!");
              if (unlikely(!tsk->pid))
                      panic("Attempted to kill the idle task!");
      
              /*
               * If do_exit is called because this processes oopsed, it's possible
               * that get_fs() was left as KERNEL_DS, so reset it to USER_DS before
               * continuing. Amongst other possible reasons, this is to prevent
               * mm_release()->clear_child_tid() from writing to a user-controlled
               * kernel address.
               */
              set_fs(USER_DS);
      
              ptrace_event(PTRACE_EVENT_EXIT, code);
      
              validate_creds_for_do_exit(tsk);
      
              /*
               * We're taking recursive faults here in do_exit. Safest is to just
               * leave this task alone and wait for reboot.
               */
              if (unlikely(tsk->flags & PF_EXITING)) {
                      pr_alert("Fixing recursive fault but reboot is needed!\n");
                      /*
                       * We can do this unlocked here. The futex code uses
                       * this flag just to verify whether the pi state
                       * cleanup has been done or not. In the worst case it
                       * loops once more. We pretend that the cleanup was
                       * done as there is no way to return. Either the
                       * OWNER_DIED bit is set by now or we push the blocked
                       * task into the wait for ever nirwana as well.
                       */
                      tsk->flags |= PF_EXITPIDONE;
                      set_current_state(TASK_UNINTERRUPTIBLE);
                      schedule();
              }
      
              exit_signals(tsk);  /* sets PF_EXITING */
              /*
               * Ensure that all new tsk->pi_lock acquisitions must observe
               * PF_EXITING. Serializes against futex.c:attach_to_pi_owner().
               */
              smp_mb();
              /*
               * Ensure that we must observe the pi_state in exit_mm() ->
               * mm_release() -> exit_pi_state_list().
               */
              raw_spin_lock_irq(&tsk->pi_lock);
              raw_spin_unlock_irq(&tsk->pi_lock);
      
              if (unlikely(in_atomic())) {
                      pr_info("note: %s[%d] exited with preempt_count %d\n",
                              current->comm, task_pid_nr(current),
                              preempt_count());
                      preempt_count_set(PREEMPT_ENABLED);
              }
      
              /* sync mm's RSS info before statistics gathering */
              if (tsk->mm)
                      sync_mm_rss(tsk->mm);
              acct_update_integrals(tsk);
              group_dead = atomic_dec_and_test(&tsk->signal->live);
              if (group_dead) {
      #ifdef CONFIG_POSIX_TIMERS
                      hrtimer_cancel(&tsk->signal->real_timer);
                      exit_itimers(tsk->signal);
      #endif
                      if (tsk->mm)
                              setmax_mm_hiwater_rss(&tsk->signal->maxrss, tsk->mm);
              }
              acct_collect(code, group_dead);
              if (group_dead)
                      tty_audit_exit();
              audit_free(tsk);
      
              tsk->exit_code = code;
              taskstats_exit(tsk, group_dead);
      
              exit_mm();
      
              if (group_dead)
                      acct_process();
              trace_sched_process_exit(tsk);
      
              exit_sem(tsk);
              exit_shm(tsk);
              exit_files(tsk);
              exit_fs(tsk);
              if (group_dead)
                      disassociate_ctty(1);
              exit_task_namespaces(tsk);
              exit_task_work(tsk);
              exit_thread(tsk);
              exit_umh(tsk);
      
              /*
               * Flush inherited counters to the parent - before the parent
               * gets woken up by child-exit notifications.
               *
               * because of cgroup mode, must be called before cgroup_exit()
               */
              perf_event_exit_task(tsk);
      
              sched_autogroup_exit_task(tsk);
              cgroup_exit(tsk);
      
              /*
               * FIXME: do that only when needed, using sched_exit tracepoint
               */
              flush_ptrace_hw_breakpoint(tsk);
      
              exit_tasks_rcu_start();
              exit_notify(tsk, group_dead);
              proc_exit_connector(tsk);
              mpol_put_task_policy(tsk);
      #ifdef CONFIG_FUTEX
              if (unlikely(current->pi_state_cache))
                      kfree(current->pi_state_cache);
      #endif
              /*
               * Make sure we are holding no locks:
               */
              debug_check_no_locks_held();
              /*
               * We can do this unlocked here. The futex code uses this flag
               * just to verify whether the pi state cleanup has been done
               * or not. In the worst case it loops once more.
               */
              tsk->flags |= PF_EXITPIDONE;
      
              if (tsk->io_context)
                      exit_io_context(tsk);
      
              if (tsk->splice_pipe)
                      free_pipe_info(tsk->splice_pipe);
      
              if (tsk->task_frag.page)
                      put_page(tsk->task_frag.page);
      
              validate_creds_for_do_exit(tsk);
      
              check_stack_usage();
              preempt_disable();
              if (tsk->nr_dirtied)
                      __this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied);
              exit_rcu();
              exit_tasks_rcu_finish();
      
              lockdep_free_task(tsk);
              do_task_dead();
      }
      EXPORT_SYMBOL_GPL(do_exit);
      
      void complete_and_exit(struct completion *comp, long code)
      {
              if (comp)
                      complete(comp);
      
              do_exit(code);
      }
      EXPORT_SYMBOL(complete_and_exit);
      
      SYSCALL_DEFINE1(exit, int, error_code)
      {
              do_exit((error_code&0xff)<<8);
      }
      
      /*
       * Take down every thread in the group.  This is called by fatal signals
       * as well as by sys_exit_group (below).
       */
      void
      do_group_exit(int exit_code)
      {
              struct signal_struct *sig = current->signal;
      
              BUG_ON(exit_code & 0x80); /* core dumps don't get here */
      
              if (signal_group_exit(sig))
                      exit_code = sig->group_exit_code;
              else if (!thread_group_empty(current)) {
                      struct sighand_struct *const sighand = current->sighand;
      
                      spin_lock_irq(&sighand->siglock);
                      if (signal_group_exit(sig))
                              /* Another thread got here before we took the lock.  */
                              exit_code = sig->group_exit_code;
                      else {
                              sig->group_exit_code = exit_code;
                              sig->flags = SIGNAL_GROUP_EXIT;
                              zap_other_threads(current);
                      }
                      spin_unlock_irq(&sighand->siglock);
              }
      
              do_exit(exit_code);
              /* NOTREACHED */
      }
      
      /*
       * this kills every thread in the thread group. Note that any externally
       * wait4()-ing process will get the correct exit code - even if this
       * thread is not the thread group leader.
       */
      SYSCALL_DEFINE1(exit_group, int, error_code)
      {
              do_group_exit((error_code & 0xff) << 8);
              /* NOTREACHED */
              return 0;
      }
      
      struct waitid_info {
              pid_t pid;
              uid_t uid;
              int status;
              int cause;
      };
      
      struct wait_opts {
              enum pid_type                wo_type;
              int                        wo_flags;
              struct pid                *wo_pid;
      
              struct waitid_info        *wo_info;
              int                        wo_stat;
              struct rusage                *wo_rusage;
      
              wait_queue_entry_t                child_wait;
              int                        notask_error;
      };
      
      static int eligible_pid(struct wait_opts *wo, struct task_struct *p)
      {
              return        wo->wo_type == PIDTYPE_MAX ||
                      task_pid_type(p, wo->wo_type) == wo->wo_pid;
      }
      
      static int
      eligible_child(struct wait_opts *wo, bool ptrace, struct task_struct *p)
      {
              if (!eligible_pid(wo, p))
                      return 0;
      
              /*
               * Wait for all children (clone and not) if __WALL is set or
               * if it is traced by us.
               */
              if (ptrace || (wo->wo_flags & __WALL))
                      return 1;
      
              /*
               * Otherwise, wait for clone children *only* if __WCLONE is set;
               * otherwise, wait for non-clone children *only*.
               *
               * Note: a "clone" child here is one that reports to its parent
               * using a signal other than SIGCHLD, or a non-leader thread which
               * we can only see if it is traced by us.
               */
              if ((p->exit_signal != SIGCHLD) ^ !!(wo->wo_flags & __WCLONE))
                      return 0;
      
              return 1;
      }
      
      /*
       * Handle sys_wait4 work for one task in state EXIT_ZOMBIE.  We hold
       * read_lock(&tasklist_lock) on entry.  If we return zero, we still hold
       * the lock and this task is uninteresting.  If we return nonzero, we have
       * released the lock and the system call should return.
       */
      static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
      {
              int state, status;
              pid_t pid = task_pid_vnr(p);
              uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p));
              struct waitid_info *infop;
      
              if (!likely(wo->wo_flags & WEXITED))
                      return 0;
      
              if (unlikely(wo->wo_flags & WNOWAIT)) {
                      status = p->exit_code;
                      get_task_struct(p);
                      read_unlock(&tasklist_lock);
                      sched_annotate_sleep();
                      if (wo->wo_rusage)
                              getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
                      put_task_struct(p);
                      goto out_info;
              }
              /*
               * Move the task's state to DEAD/TRACE, only one thread can do this.
               */
              state = (ptrace_reparented(p) && thread_group_leader(p)) ?
                      EXIT_TRACE : EXIT_DEAD;
              if (cmpxchg(&p->exit_state, EXIT_ZOMBIE, state) != EXIT_ZOMBIE)
                      return 0;
              /*
               * We own this thread, nobody else can reap it.
               */
              read_unlock(&tasklist_lock);
              sched_annotate_sleep();
      
              /*
               * Check thread_group_leader() to exclude the traced sub-threads.
               */
              if (state == EXIT_DEAD && thread_group_leader(p)) {
                      struct signal_struct *sig = p->signal;
                      struct signal_struct *psig = current->signal;
                      unsigned long maxrss;
                      u64 tgutime, tgstime;
      
                      /*
                       * The resource counters for the group leader are in its
                       * own task_struct.  Those for dead threads in the group
                       * are in its signal_struct, as are those for the child
                       * processes it has previously reaped.  All these
                       * accumulate in the parent's signal_struct c* fields.
                       *
                       * We don't bother to take a lock here to protect these
                       * p->signal fields because the whole thread group is dead
                       * and nobody can change them.
                       *
                       * psig->stats_lock also protects us from our sub-theads
                       * which can reap other children at the same time. Until
                       * we change k_getrusage()-like users to rely on this lock
                       * we have to take ->siglock as well.
                       *
                       * We use thread_group_cputime_adjusted() to get times for
                       * the thread group, which consolidates times for all threads
                       * in the group including the group leader.
                       */
                      thread_group_cputime_adjusted(p, &tgutime, &tgstime);
                      spin_lock_irq(&current->sighand->siglock);
                      write_seqlock(&psig->stats_lock);
                      psig->cutime += tgutime + sig->cutime;
                      psig->cstime += tgstime + sig->cstime;
                      psig->cgtime += task_gtime(p) + sig->gtime + sig->cgtime;
                      psig->cmin_flt +=
                              p->min_flt + sig->min_flt + sig->cmin_flt;
                      psig->cmaj_flt +=
                              p->maj_flt + sig->maj_flt + sig->cmaj_flt;
                      psig->cnvcsw +=
                              p->nvcsw + sig->nvcsw + sig->cnvcsw;
                      psig->cnivcsw +=
                              p->nivcsw + sig->nivcsw + sig->cnivcsw;
                      psig->cinblock +=
                              task_io_get_inblock(p) +
                              sig->inblock + sig->cinblock;
                      psig->coublock +=
                              task_io_get_oublock(p) +
                              sig->oublock + sig->coublock;
                      maxrss = max(sig->maxrss, sig->cmaxrss);
                      if (psig->cmaxrss < maxrss)
                              psig->cmaxrss = maxrss;
                      task_io_accounting_add(&psig->ioac, &p->ioac);
                      task_io_accounting_add(&psig->ioac, &sig->ioac);
                      write_sequnlock(&psig->stats_lock);
                      spin_unlock_irq(&current->sighand->siglock);
              }
      
              if (wo->wo_rusage)
                      getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
              status = (p->signal->flags & SIGNAL_GROUP_EXIT)
                      ? p->signal->group_exit_code : p->exit_code;
              wo->wo_stat = status;
      
              if (state == EXIT_TRACE) {
                      write_lock_irq(&tasklist_lock);
                      /* We dropped tasklist, ptracer could die and untrace */
                      ptrace_unlink(p);
      
                      /* If parent wants a zombie, don't release it now */
                      state = EXIT_ZOMBIE;
                      if (do_notify_parent(p, p->exit_signal))
                              state = EXIT_DEAD;
                      p->exit_state = state;
                      write_unlock_irq(&tasklist_lock);
              }
              if (state == EXIT_DEAD)
                      release_task(p);
      
      out_info:
              infop = wo->wo_info;
              if (infop) {
                      if ((status & 0x7f) == 0) {
                              infop->cause = CLD_EXITED;
                              infop->status = status >> 8;
                      } else {
                              infop->cause = (status & 0x80) ? CLD_DUMPED : CLD_KILLED;
                              infop->status = status & 0x7f;
                      }
                      infop->pid = pid;
                      infop->uid = uid;
              }
      
              return pid;
      }
      
      static int *task_stopped_code(struct task_struct *p, bool ptrace)
      {
              if (ptrace) {
                      if (task_is_traced(p) && !(p->jobctl & JOBCTL_LISTENING))
                              return &p->exit_code;
              } else {
                      if (p->signal->flags & SIGNAL_STOP_STOPPED)
                              return &p->signal->group_exit_code;
              }
              return NULL;
      }
      
      /**
       * wait_task_stopped - Wait for %TASK_STOPPED or %TASK_TRACED
       * @wo: wait options
       * @ptrace: is the wait for ptrace
       * @p: task to wait for
       *
       * Handle sys_wait4() work for %p in state %TASK_STOPPED or %TASK_TRACED.
       *
       * CONTEXT:
       * read_lock(&tasklist_lock), which is released if return value is
       * non-zero.  Also, grabs and releases @p->sighand->siglock.
       *
       * RETURNS:
       * 0 if wait condition didn't exist and search for other wait conditions
       * should continue.  Non-zero return, -errno on failure and @p's pid on
       * success, implies that tasklist_lock is released and wait condition
       * search should terminate.
       */
      static int wait_task_stopped(struct wait_opts *wo,
                                      int ptrace, struct task_struct *p)
      {
              struct waitid_info *infop;
              int exit_code, *p_code, why;
              uid_t uid = 0; /* unneeded, required by compiler */
              pid_t pid;
      
              /*
               * Traditionally we see ptrace'd stopped tasks regardless of options.
               */
              if (!ptrace && !(wo->wo_flags & WUNTRACED))
                      return 0;
      
              if (!task_stopped_code(p, ptrace))
                      return 0;
      
              exit_code = 0;
              spin_lock_irq(&p->sighand->siglock);
      
              p_code = task_stopped_code(p, ptrace);
              if (unlikely(!p_code))
                      goto unlock_sig;
      
              exit_code = *p_code;
              if (!exit_code)
                      goto unlock_sig;
      
              if (!unlikely(wo->wo_flags & WNOWAIT))
                      *p_code = 0;
      
              uid = from_kuid_munged(current_user_ns(), task_uid(p));
      unlock_sig:
              spin_unlock_irq(&p->sighand->siglock);
              if (!exit_code)
                      return 0;
      
              /*
               * Now we are pretty sure this task is interesting.
               * Make sure it doesn't get reaped out from under us while we
               * give up the lock and then examine it below.  We don't want to
               * keep holding onto the tasklist_lock while we call getrusage and
               * possibly take page faults for user memory.
               */
              get_task_struct(p);
              pid = task_pid_vnr(p);
              why = ptrace ? CLD_TRAPPED : CLD_STOPPED;
              read_unlock(&tasklist_lock);
              sched_annotate_sleep();
              if (wo->wo_rusage)
                      getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
              put_task_struct(p);
      
              if (likely(!(wo->wo_flags & WNOWAIT)))
                      wo->wo_stat = (exit_code << 8) | 0x7f;
      
              infop = wo->wo_info;
              if (infop) {
                      infop->cause = why;
                      infop->status = exit_code;
                      infop->pid = pid;
                      infop->uid = uid;
              }
              return pid;
      }
      
      /*
       * Handle do_wait work for one task in a live, non-stopped state.
       * read_lock(&tasklist_lock) on entry.  If we return zero, we still hold
       * the lock and this task is uninteresting.  If we return nonzero, we have
       * released the lock and the system call should return.
       */
      static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
      {
              struct waitid_info *infop;
              pid_t pid;
              uid_t uid;
      
              if (!unlikely(wo->wo_flags & WCONTINUED))
                      return 0;
      
              if (!(p->signal->flags & SIGNAL_STOP_CONTINUED))
                      return 0;
      
              spin_lock_irq(&p->sighand->siglock);
              /* Re-check with the lock held.  */
              if (!(p->signal->flags & SIGNAL_STOP_CONTINUED)) {
                      spin_unlock_irq(&p->sighand->siglock);
                      return 0;
              }
              if (!unlikely(wo->wo_flags & WNOWAIT))
                      p->signal->flags &= ~SIGNAL_STOP_CONTINUED;
              uid = from_kuid_munged(current_user_ns(), task_uid(p));
              spin_unlock_irq(&p->sighand->siglock);
      
              pid = task_pid_vnr(p);
              get_task_struct(p);
              read_unlock(&tasklist_lock);
              sched_annotate_sleep();
              if (wo->wo_rusage)
                      getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
              put_task_struct(p);
      
              infop = wo->wo_info;
              if (!infop) {
                      wo->wo_stat = 0xffff;
              } else {
                      infop->cause = CLD_CONTINUED;
                      infop->pid = pid;
                      infop->uid = uid;
                      infop->status = SIGCONT;
              }
              return pid;
      }
      
      /*
       * Consider @p for a wait by @parent.
       *
       * -ECHILD should be in ->notask_error before the first call.
       * Returns nonzero for a final return, when we have unlocked tasklist_lock.
       * Returns zero if the search for a child should continue;
       * then ->notask_error is 0 if @p is an eligible child,
       * or still -ECHILD.
       */
      static int wait_consider_task(struct wait_opts *wo, int ptrace,
                                      struct task_struct *p)
      {
              /*
               * We can race with wait_task_zombie() from another thread.
               * Ensure that EXIT_ZOMBIE -> EXIT_DEAD/EXIT_TRACE transition
               * can't confuse the checks below.
               */
              int exit_state = READ_ONCE(p->exit_state);
              int ret;
      
              if (unlikely(exit_state == EXIT_DEAD))
                      return 0;
      
              ret = eligible_child(wo, ptrace, p);
              if (!ret)
                      return ret;
      
              if (unlikely(exit_state == EXIT_TRACE)) {
                      /*
                       * ptrace == 0 means we are the natural parent. In this case
                       * we should clear notask_error, debugger will notify us.
                       */
                      if (likely(!ptrace))
                              wo->notask_error = 0;
                      return 0;
              }
      
              if (likely(!ptrace) && unlikely(p->ptrace)) {
                      /*
                       * If it is traced by its real parent's group, just pretend
                       * the caller is ptrace_do_wait() and reap this child if it
                       * is zombie.
                       *
                       * This also hides group stop state from real parent; otherwise
                       * a single stop can be reported twice as group and ptrace stop.
                       * If a ptracer wants to distinguish these two events for its
                       * own children it should create a separate process which takes
                       * the role of real parent.
                       */
                      if (!ptrace_reparented(p))
                              ptrace = 1;
              }
      
              /* slay zombie? */
              if (exit_state == EXIT_ZOMBIE) {
                      /* we don't reap group leaders with subthreads */
                      if (!delay_group_leader(p)) {
                              /*
                               * A zombie ptracee is only visible to its ptracer.
                               * Notification and reaping will be cascaded to the
                               * real parent when the ptracer detaches.
                               */
                              if (unlikely(ptrace) || likely(!p->ptrace))
                                      return wait_task_zombie(wo, p);
                      }
      
                      /*
                       * Allow access to stopped/continued state via zombie by
                       * falling through.  Clearing of notask_error is complex.
                       *
                       * When !@ptrace:
                       *
                       * If WEXITED is set, notask_error should naturally be
                       * cleared.  If not, subset of WSTOPPED|WCONTINUED is set,
                       * so, if there are live subthreads, there are events to
                       * wait for.  If all subthreads are dead, it's still safe
                       * to clear - this function will be called again in finite
                       * amount time once all the subthreads are released and
                       * will then return without clearing.
                       *
                       * When @ptrace:
                       *
                       * Stopped state is per-task and thus can't change once the
                       * target task dies.  Only continued and exited can happen.
                       * Clear notask_error if WCONTINUED | WEXITED.
                       */
                      if (likely(!ptrace) || (wo->wo_flags & (WCONTINUED | WEXITED)))
                              wo->notask_error = 0;
              } else {
                      /*
                       * @p is alive and it's gonna stop, continue or exit, so
                       * there always is something to wait for.
                       */
                      wo->notask_error = 0;
              }
      
              /*
               * Wait for stopped.  Depending on @ptrace, different stopped state
               * is used and the two don't interact with each other.
               */
              ret = wait_task_stopped(wo, ptrace, p);
              if (ret)
                      return ret;
      
              /*
               * Wait for continued.  There's only one continued state and the
               * ptracer can consume it which can confuse the real parent.  Don't
               * use WCONTINUED from ptracer.  You don't need or want it.
               */
              return wait_task_continued(wo, p);
      }
      
      /*
       * Do the work of do_wait() for one thread in the group, @tsk.
       *
       * -ECHILD should be in ->notask_error before the first call.
       * Returns nonzero for a final return, when we have unlocked tasklist_lock.
       * Returns zero if the search for a child should continue; then
       * ->notask_error is 0 if there were any eligible children,
       * or still -ECHILD.
       */
      static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk)
      {
              struct task_struct *p;
      
              list_for_each_entry(p, &tsk->children, sibling) {
                      int ret = wait_consider_task(wo, 0, p);
      
                      if (ret)
                              return ret;
              }
      
              return 0;
      }
      
      static int ptrace_do_wait(struct wait_opts *wo, struct task_struct *tsk)
      {
              struct task_struct *p;
      
              list_for_each_entry(p, &tsk->ptraced, ptrace_entry) {
                      int ret = wait_consider_task(wo, 1, p);
      
                      if (ret)
                              return ret;
              }
      
              return 0;
      }
      
      static int child_wait_callback(wait_queue_entry_t *wait, unsigned mode,
                                      int sync, void *key)
      {
              struct wait_opts *wo = container_of(wait, struct wait_opts,
                                                      child_wait);
              struct task_struct *p = key;
      
              if (!eligible_pid(wo, p))
                      return 0;
      
              if ((wo->wo_flags & __WNOTHREAD) && wait->private != p->parent)
                      return 0;
      
              return default_wake_function(wait, mode, sync, key);
      }
      
      void __wake_up_parent(struct task_struct *p, struct task_struct *parent)
      {
              __wake_up_sync_key(&parent->signal->wait_chldexit,
                                      TASK_INTERRUPTIBLE, 1, p);
      }
      
      static long do_wait(struct wait_opts *wo)
      {
              struct task_struct *tsk;
              int retval;
      
              trace_sched_process_wait(wo->wo_pid);
      
              init_waitqueue_func_entry(&wo->child_wait, child_wait_callback);
              wo->child_wait.private = current;
              add_wait_queue(&current->signal->wait_chldexit, &wo->child_wait);
      repeat:
              /*
               * If there is nothing that can match our criteria, just get out.
               * We will clear ->notask_error to zero if we see any child that
               * might later match our criteria, even if we are not able to reap
               * it yet.
               */
              wo->notask_error = -ECHILD;
              if ((wo->wo_type < PIDTYPE_MAX) &&
                 (!wo->wo_pid || hlist_empty(&wo->wo_pid->tasks[wo->wo_type])))
                      goto notask;
      
              set_current_state(TASK_INTERRUPTIBLE);
              read_lock(&tasklist_lock);
              tsk = current;
              do {
                      retval = do_wait_thread(wo, tsk);
                      if (retval)
                              goto end;
      
                      retval = ptrace_do_wait(wo, tsk);
                      if (retval)
                              goto end;
      
                      if (wo->wo_flags & __WNOTHREAD)
                              break;
              } while_each_thread(current, tsk);
              read_unlock(&tasklist_lock);
      
      notask:
              retval = wo->notask_error;
              if (!retval && !(wo->wo_flags & WNOHANG)) {
                      retval = -ERESTARTSYS;
                      if (!signal_pending(current)) {
                              schedule();
                              goto repeat;
                      }
              }
      end:
              __set_current_state(TASK_RUNNING);
              remove_wait_queue(&current->signal->wait_chldexit, &wo->child_wait);
              return retval;
      }
      
      static struct pid *pidfd_get_pid(unsigned int fd)
      {
              struct fd f;
              struct pid *pid;
      
              f = fdget(fd);
              if (!f.file)
                      return ERR_PTR(-EBADF);
      
              pid = pidfd_pid(f.file);
              if (!IS_ERR(pid))
                      get_pid(pid);
      
              fdput(f);
              return pid;
      }
      
      static long kernel_waitid(int which, pid_t upid, struct waitid_info *infop,
                                int options, struct rusage *ru)
      {
              struct wait_opts wo;
              struct pid *pid = NULL;
              enum pid_type type;
              long ret;
      
              if (options & ~(WNOHANG|WNOWAIT|WEXITED|WSTOPPED|WCONTINUED|
                              __WNOTHREAD|__WCLONE|__WALL))
                      return -EINVAL;
              if (!(options & (WEXITED|WSTOPPED|WCONTINUED)))
                      return -EINVAL;
      
              switch (which) {
              case P_ALL:
                      type = PIDTYPE_MAX;
                      break;
              case P_PID:
                      type = PIDTYPE_PID;
                      if (upid <= 0)
                              return -EINVAL;
      
                      pid = find_get_pid(upid);
                      break;
              case P_PGID:
                      type = PIDTYPE_PGID;
                      if (upid < 0)
                              return -EINVAL;
      
                      if (upid)
                              pid = find_get_pid(upid);
                      else
                              pid = get_task_pid(current, PIDTYPE_PGID);
                      break;
              case P_PIDFD:
                      type = PIDTYPE_PID;
                      if (upid < 0)
                              return -EINVAL;
      
                      pid = pidfd_get_pid(upid);
                      if (IS_ERR(pid))
                              return PTR_ERR(pid);
                      break;
              default:
                      return -EINVAL;
              }
      
              wo.wo_type        = type;
              wo.wo_pid        = pid;
              wo.wo_flags        = options;
              wo.wo_info        = infop;
              wo.wo_rusage        = ru;
              ret = do_wait(&wo);
      
              put_pid(pid);
              return ret;
      }
      
      SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
                      infop, int, options, struct rusage __user *, ru)
      {
              struct rusage r;
              struct waitid_info info = {.status = 0};
              long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
              int signo = 0;
      
              if (err > 0) {
                      signo = SIGCHLD;
                      err = 0;
                      if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
                              return -EFAULT;
              }
              if (!infop)
                      return err;
      
              if (!user_access_begin(infop, sizeof(*infop)))
                      return -EFAULT;
      
              unsafe_put_user(signo, &infop->si_signo, Efault);
              unsafe_put_user(0, &infop->si_errno, Efault);
              unsafe_put_user(info.cause, &infop->si_code, Efault);
              unsafe_put_user(info.pid, &infop->si_pid, Efault);
              unsafe_put_user(info.uid, &infop->si_uid, Efault);
              unsafe_put_user(info.status, &infop->si_status, Efault);
              user_access_end();
              return err;
      Efault:
              user_access_end();
              return -EFAULT;
      }
      
      long kernel_wait4(pid_t upid, int __user *stat_addr, int options,
                        struct rusage *ru)
      {
              struct wait_opts wo;
              struct pid *pid = NULL;
              enum pid_type type;
              long ret;
      
              if (options & ~(WNOHANG|WUNTRACED|WCONTINUED|
                              __WNOTHREAD|__WCLONE|__WALL))
                      return -EINVAL;
      
              /* -INT_MIN is not defined */
              if (upid == INT_MIN)
                      return -ESRCH;
      
              if (upid == -1)
                      type = PIDTYPE_MAX;
              else if (upid < 0) {
                      type = PIDTYPE_PGID;
                      pid = find_get_pid(-upid);
              } else if (upid == 0) {
                      type = PIDTYPE_PGID;
                      pid = get_task_pid(current, PIDTYPE_PGID);
              } else /* upid > 0 */ {
                      type = PIDTYPE_PID;
                      pid = find_get_pid(upid);
              }
      
              wo.wo_type        = type;
              wo.wo_pid        = pid;
              wo.wo_flags        = options | WEXITED;
              wo.wo_info        = NULL;
              wo.wo_stat        = 0;
              wo.wo_rusage        = ru;
              ret = do_wait(&wo);
              put_pid(pid);
              if (ret > 0 && stat_addr && put_user(wo.wo_stat, stat_addr))
                      ret = -EFAULT;
      
              return ret;
      }
      
      SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
                      int, options, struct rusage __user *, ru)
      {
              struct rusage r;
              long err = kernel_wait4(upid, stat_addr, options, ru ? &r : NULL);
      
              if (err > 0) {
                      if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
                              return -EFAULT;
              }
              return err;
      }
      
      #ifdef __ARCH_WANT_SYS_WAITPID
      
      /*
       * sys_waitpid() remains for compatibility. waitpid() should be
       * implemented by calling sys_wait4() from libc.a.
       */
      SYSCALL_DEFINE3(waitpid, pid_t, pid, int __user *, stat_addr, int, options)
      {
              return kernel_wait4(pid, stat_addr, options, NULL);
      }
      
      #endif
      
      #ifdef CONFIG_COMPAT
      COMPAT_SYSCALL_DEFINE4(wait4,
              compat_pid_t, pid,
              compat_uint_t __user *, stat_addr,
              int, options,
              struct compat_rusage __user *, ru)
      {
              struct rusage r;
              long err = kernel_wait4(pid, stat_addr, options, ru ? &r : NULL);
              if (err > 0) {
                      if (ru && put_compat_rusage(&r, ru))
                              return -EFAULT;
              }
              return err;
      }
      
      COMPAT_SYSCALL_DEFINE5(waitid,
                      int, which, compat_pid_t, pid,
                      struct compat_siginfo __user *, infop, int, options,
                      struct compat_rusage __user *, uru)
      {
              struct rusage ru;
              struct waitid_info info = {.status = 0};
              long err = kernel_waitid(which, pid, &info, options, uru ? &ru : NULL);
              int signo = 0;
              if (err > 0) {
                      signo = SIGCHLD;
                      err = 0;
                      if (uru) {
                              /* kernel_waitid() overwrites everything in ru */
                              if (COMPAT_USE_64BIT_TIME)
                                      err = copy_to_user(uru, &ru, sizeof(ru));
                              else
                                      err = put_compat_rusage(&ru, uru);
                              if (err)
                                      return -EFAULT;
                      }
              }
      
              if (!infop)
                      return err;
      
              if (!user_access_begin(infop, sizeof(*infop)))
                      return -EFAULT;
      
              unsafe_put_user(signo, &infop->si_signo, Efault);
              unsafe_put_user(0, &infop->si_errno, Efault);
              unsafe_put_user(info.cause, &infop->si_code, Efault);
              unsafe_put_user(info.pid, &infop->si_pid, Efault);
              unsafe_put_user(info.uid, &infop->si_uid, Efault);
              unsafe_put_user(info.status, &infop->si_status, Efault);
              user_access_end();
              return err;
      Efault:
              user_access_end();
              return -EFAULT;
      }
      #endif
      
      __weak void abort(void)
      {
              BUG();
      
              /* if that doesn't kill us, halt */
              panic("Oops failed to kill thread");
      }
      EXPORT_SYMBOL(abort);
      // SPDX-License-Identifier: GPL-2.0-only
      /*
       * drivers/acpi/device_sysfs.c - ACPI device sysfs attributes and modalias.
       *
       * Copyright (C) 2015, Intel Corp.
       * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
       * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
       *
       * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       *
       * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       */
      
      #include <linux/acpi.h>
      #include <linux/device.h>
      #include <linux/export.h>
      #include <linux/nls.h>
      
      #include "internal.h"
      
      static ssize_t acpi_object_path(acpi_handle handle, char *buf)
      {
              struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
              int result;
      
              result = acpi_get_name(handle, ACPI_FULL_PATHNAME, &path);
              if (result)
                      return result;
      
              result = sprintf(buf, "%s\n", (char *)path.pointer);
              kfree(path.pointer);
              return result;
      }
      
      struct acpi_data_node_attr {
              struct attribute attr;
              ssize_t (*show)(struct acpi_data_node *, char *);
              ssize_t (*store)(struct acpi_data_node *, const char *, size_t count);
      };
      
      #define DATA_NODE_ATTR(_name)                        \
              static struct acpi_data_node_attr data_node_##_name =        \
                      __ATTR(_name, 0444, data_node_show_##_name, NULL)
      
      static ssize_t data_node_show_path(struct acpi_data_node *dn, char *buf)
      {
              return dn->handle ? acpi_object_path(dn->handle, buf) : 0;
      }
      
      DATA_NODE_ATTR(path);
      
      static struct attribute *acpi_data_node_default_attrs[] = {
              &data_node_path.attr,
              NULL
      };
      
      #define to_data_node(k) container_of(k, struct acpi_data_node, kobj)
      #define to_attr(a) container_of(a, struct acpi_data_node_attr, attr)
      
      static ssize_t acpi_data_node_attr_show(struct kobject *kobj,
                                              struct attribute *attr, char *buf)
      {
              struct acpi_data_node *dn = to_data_node(kobj);
              struct acpi_data_node_attr *dn_attr = to_attr(attr);
      
              return dn_attr->show ? dn_attr->show(dn, buf) : -ENXIO;
      }
      
      static const struct sysfs_ops acpi_data_node_sysfs_ops = {
              .show        = acpi_data_node_attr_show,
      };
      
      static void acpi_data_node_release(struct kobject *kobj)
      {
              struct acpi_data_node *dn = to_data_node(kobj);
              complete(&dn->kobj_done);
      }
      
      static struct kobj_type acpi_data_node_ktype = {
              .sysfs_ops = &acpi_data_node_sysfs_ops,
              .default_attrs = acpi_data_node_default_attrs,
              .release = acpi_data_node_release,
      };
      
      static void acpi_expose_nondev_subnodes(struct kobject *kobj,
                                              struct acpi_device_data *data)
      {
              struct list_head *list = &data->subnodes;
              struct acpi_data_node *dn;
      
              if (list_empty(list))
                      return;
      
              list_for_each_entry(dn, list, sibling) {
                      int ret;
      
                      init_completion(&dn->kobj_done);
                      ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype,
                                                 kobj, "%s", dn->name);
                      if (!ret)
                              acpi_expose_nondev_subnodes(&dn->kobj, &dn->data);
                      else if (dn->handle)
                              acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret);
              }
      }
      
      static void acpi_hide_nondev_subnodes(struct acpi_device_data *data)
      {
              struct list_head *list = &data->subnodes;
              struct acpi_data_node *dn;
      
              if (list_empty(list))
                      return;
      
              list_for_each_entry_reverse(dn, list, sibling) {
                      acpi_hide_nondev_subnodes(&dn->data);
                      kobject_put(&dn->kobj);
              }
      }
      
      /**
       * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
       * @acpi_dev: ACPI device object.
       * @modalias: Buffer to print into.
       * @size: Size of the buffer.
       *
       * Creates hid/cid(s) string needed for modalias and uevent
       * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
       * char *modalias: "acpi:IBM0001:ACPI0001"
       * Return: 0: no _HID and no _CID
       *         -EINVAL: output error
       *         -ENOMEM: output is truncated
      */
      static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
                                     int size)
      {
              int len;
              int count;
              struct acpi_hardware_id *id;
      
              /* Avoid unnecessarily loading modules for non present devices. */
              if (!acpi_device_is_present(acpi_dev))
                      return 0;
      
              /*
               * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
               * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
               * device's list.
               */
              count = 0;
              list_for_each_entry(id, &acpi_dev->pnp.ids, list)
                      if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))
                              count++;
      
              if (!count)
                      return 0;
      
              len = snprintf(modalias, size, "acpi:");
              if (len <= 0)
                      return len;
      
              size -= len;
      
              list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
                      if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))
                              continue;
      
                      count = snprintf(&modalias[len], size, "%s:", id->id);
                      if (count < 0)
                              return -EINVAL;
      
                      if (count >= size)
                              return -ENOMEM;
      
                      len += count;
                      size -= count;
              }
              modalias[len] = '\0';
              return len;
      }
      
      /**
       * create_of_modalias - Creates DT compatible string for modalias and uevent
       * @acpi_dev: ACPI device object.
       * @modalias: Buffer to print into.
       * @size: Size of the buffer.
       *
       * Expose DT compatible modalias as of:NnameTCcompatible.  This function should
       * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of
       * ACPI/PNP IDs.
       */
      static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
                                    int size)
      {
              struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
              const union acpi_object *of_compatible, *obj;
              acpi_status status;
              int len, count;
              int i, nval;
              char *c;
      
              status = acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
              if (ACPI_FAILURE(status))
                      return -ENODEV;
      
              /* DT strings are all in lower case */
              for (c = buf.pointer; *c != '\0'; c++)
                      *c = tolower(*c);
      
              len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
              ACPI_FREE(buf.pointer);
      
              if (len <= 0)
                      return len;
      
              of_compatible = acpi_dev->data.of_compatible;
              if (of_compatible->type == ACPI_TYPE_PACKAGE) {
                      nval = of_compatible->package.count;
                      obj = of_compatible->package.elements;
              } else { /* Must be ACPI_TYPE_STRING. */
                      nval = 1;
                      obj = of_compatible;
              }
              for (i = 0; i < nval; i++, obj++) {
                      count = snprintf(&modalias[len], size, "C%s",
                                       obj->string.pointer);
                      if (count < 0)
                              return -EINVAL;
      
                      if (count >= size)
                              return -ENOMEM;
      
                      len += count;
                      size -= count;
              }
              modalias[len] = '\0';
              return len;
      }
      
   10 int __acpi_device_uevent_modalias(struct acpi_device *adev,
                                        struct kobj_uevent_env *env)
      {
              int len;
      
   10         if (!adev)
                      return -ENODEV;
      
              if (list_empty(&adev->pnp.ids))
                      return 0;
      
              if (add_uevent_var(env, "MODALIAS="))
                      return -ENOMEM;
      
              len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
                                        sizeof(env->buf) - env->buflen);
              if (len < 0)
                      return len;
      
              env->buflen += len;
              if (!adev->data.of_compatible)
                      return 0;
      
              if (len > 0 && add_uevent_var(env, "MODALIAS="))
                      return -ENOMEM;
      
              len = create_of_modalias(adev, &env->buf[env->buflen - 1],
                                       sizeof(env->buf) - env->buflen);
              if (len < 0)
                      return len;
      
              env->buflen += len;
      
   10         return 0;
      }
      
      /**
       * acpi_device_uevent_modalias - uevent modalias for ACPI-enumerated devices.
       *
       * Create the uevent modalias field for ACPI-enumerated devices.
       *
       * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
       * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
       */
      int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
      {
   10         return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);
      }
      EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
      
      static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)
      {
              int len, count;
      
              if (!adev)
                      return -ENODEV;
      
              if (list_empty(&adev->pnp.ids))
                      return 0;
      
              len = create_pnp_modalias(adev, buf, size - 1);
              if (len < 0) {
                      return len;
              } else if (len > 0) {
                      buf[len++] = '\n';
                      size -= len;
              }
              if (!adev->data.of_compatible)
                      return len;
      
              count = create_of_modalias(adev, buf + len, size - 1);
              if (count < 0) {
                      return count;
              } else if (count > 0) {
                      len += count;
                      buf[len++] = '\n';
              }
      
              return len;
      }
      
      /**
       * acpi_device_modalias - modalias sysfs attribute for ACPI-enumerated devices.
       *
       * Create the modalias sysfs attribute for ACPI-enumerated devices.
       *
       * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
       * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
       */
      int acpi_device_modalias(struct device *dev, char *buf, int size)
      {
              return __acpi_device_modalias(acpi_companion_match(dev), buf, size);
      }
      EXPORT_SYMBOL_GPL(acpi_device_modalias);
      
      static ssize_t
      acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
      {
              return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
      }
      static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
      
      static ssize_t real_power_state_show(struct device *dev,
                                           struct device_attribute *attr, char *buf)
      {
              struct acpi_device *adev = to_acpi_device(dev);
              int state;
              int ret;
      
              ret = acpi_device_get_power(adev, &state);
              if (ret)
                      return ret;
      
              return sprintf(buf, "%s\n", acpi_power_state_string(state));
      }
      
      static DEVICE_ATTR_RO(real_power_state);
      
      static ssize_t power_state_show(struct device *dev,
                                      struct device_attribute *attr, char *buf)
      {
              struct acpi_device *adev = to_acpi_device(dev);
      
              return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));
      }
      
      static DEVICE_ATTR_RO(power_state);
      
      static ssize_t
      acpi_eject_store(struct device *d, struct device_attribute *attr,
                      const char *buf, size_t count)
      {
              struct acpi_device *acpi_device = to_acpi_device(d);
              acpi_object_type not_used;
              acpi_status status;
      
              if (!count || buf[0] != '1')
                      return -EINVAL;
      
              if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
                  && !acpi_device->driver)
                      return -ENODEV;
      
              status = acpi_get_type(acpi_device->handle, &not_used);
              if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
                      return -ENODEV;
      
              get_device(&acpi_device->dev);
              status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT);
              if (ACPI_SUCCESS(status))
                      return count;
      
              put_device(&acpi_device->dev);
              acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
                                ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
              return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
      }
      
      static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
      
      static ssize_t
      acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf)
      {
              struct acpi_device *acpi_dev = to_acpi_device(dev);
      
              return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
      }
      static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
      
      static ssize_t acpi_device_uid_show(struct device *dev,
                                          struct device_attribute *attr, char *buf)
      {
              struct acpi_device *acpi_dev = to_acpi_device(dev);
      
              return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
      }
      static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
      
      static ssize_t acpi_device_adr_show(struct device *dev,
                                          struct device_attribute *attr, char *buf)
      {
              struct acpi_device *acpi_dev = to_acpi_device(dev);
      
              if (acpi_dev->pnp.bus_address > U32_MAX)
                      return sprintf(buf, "0x%016llx\n", acpi_dev->pnp.bus_address);
              else
                      return sprintf(buf, "0x%08llx\n", acpi_dev->pnp.bus_address);
      }
      static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
      
      static ssize_t acpi_device_path_show(struct device *dev,
                                           struct device_attribute *attr, char *buf)
      {
              struct acpi_device *acpi_dev = to_acpi_device(dev);
      
              return acpi_object_path(acpi_dev->handle, buf);
      }
      static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
      
      /* sysfs file that shows description text from the ACPI _STR method */
      static ssize_t description_show(struct device *dev,
                                      struct device_attribute *attr,
                                      char *buf) {
              struct acpi_device *acpi_dev = to_acpi_device(dev);
              int result;
      
              if (acpi_dev->pnp.str_obj == NULL)
                      return 0;
      
              /*
               * The _STR object contains a Unicode identifier for a device.
               * We need to convert to utf-8 so it can be displayed.
               */
              result = utf16s_to_utf8s(
                      (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
                      acpi_dev->pnp.str_obj->buffer.length,
                      UTF16_LITTLE_ENDIAN, buf,
                      PAGE_SIZE);
      
              buf[result++] = '\n';
      
              return result;
      }
      static DEVICE_ATTR_RO(description);
      
      static ssize_t
      acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
                           char *buf) {
              struct acpi_device *acpi_dev = to_acpi_device(dev);
              acpi_status status;
              unsigned long long sun;
      
              status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
              if (ACPI_FAILURE(status))
                      return -EIO;
      
              return sprintf(buf, "%llu\n", sun);
      }
      static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
      
      static ssize_t
      acpi_device_hrv_show(struct device *dev, struct device_attribute *attr,
                           char *buf) {
              struct acpi_device *acpi_dev = to_acpi_device(dev);
              acpi_status status;
              unsigned long long hrv;
      
              status = acpi_evaluate_integer(acpi_dev->handle, "_HRV", NULL, &hrv);
              if (ACPI_FAILURE(status))
                      return -EIO;
      
              return sprintf(buf, "%llu\n", hrv);
      }
      static DEVICE_ATTR(hrv, 0444, acpi_device_hrv_show, NULL);
      
      static ssize_t status_show(struct device *dev, struct device_attribute *attr,
                                      char *buf) {
              struct acpi_device *acpi_dev = to_acpi_device(dev);
              acpi_status status;
              unsigned long long sta;
      
              status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);
              if (ACPI_FAILURE(status))
                      return -EIO;
      
              return sprintf(buf, "%llu\n", sta);
      }
      static DEVICE_ATTR_RO(status);
      
      /**
       * acpi_device_setup_files - Create sysfs attributes of an ACPI device.
       * @dev: ACPI device object.
       */
      int acpi_device_setup_files(struct acpi_device *dev)
      {
              struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
              acpi_status status;
              int result = 0;
      
              /*
               * Devices gotten from FADT don't have a "path" attribute
               */
              if (dev->handle) {
                      result = device_create_file(&dev->dev, &dev_attr_path);
                      if (result)
                              goto end;
              }
      
              if (!list_empty(&dev->pnp.ids)) {
                      result = device_create_file(&dev->dev, &dev_attr_hid);
                      if (result)
                              goto end;
      
                      result = device_create_file(&dev->dev, &dev_attr_modalias);
                      if (result)
                              goto end;
              }
      
              /*
               * If device has _STR, 'description' file is created
               */
              if (acpi_has_method(dev->handle, "_STR")) {
                      status = acpi_evaluate_object(dev->handle, "_STR",
                                              NULL, &buffer);
                      if (ACPI_FAILURE(status))
                              buffer.pointer = NULL;
                      dev->pnp.str_obj = buffer.pointer;
                      result = device_create_file(&dev->dev, &dev_attr_description);
                      if (result)
                              goto end;
              }
      
              if (dev->pnp.type.bus_address)
                      result = device_create_file(&dev->dev, &dev_attr_adr);
              if (dev->pnp.unique_id)
                      result = device_create_file(&dev->dev, &dev_attr_uid);
      
              if (acpi_has_method(dev->handle, "_SUN")) {
                      result = device_create_file(&dev->dev, &dev_attr_sun);
                      if (result)
                              goto end;
              }
      
              if (acpi_has_method(dev->handle, "_HRV")) {
                      result = device_create_file(&dev->dev, &dev_attr_hrv);
                      if (result)
                              goto end;
              }
      
              if (acpi_has_method(dev->handle, "_STA")) {
                      result = device_create_file(&dev->dev, &dev_attr_status);
                      if (result)
                              goto end;
              }
      
              /*
               * If device has _EJ0, 'eject' file is created that is used to trigger
               * hot-removal function from userland.
               */
              if (acpi_has_method(dev->handle, "_EJ0")) {
                      result = device_create_file(&dev->dev, &dev_attr_eject);
                      if (result)
                              return result;
              }
      
              if (dev->flags.power_manageable) {
                      result = device_create_file(&dev->dev, &dev_attr_power_state);
                      if (result)
                              return result;
      
                      if (dev->power.flags.power_resources)
                              result = device_create_file(&dev->dev,
                                                          &dev_attr_real_power_state);
              }
      
              acpi_expose_nondev_subnodes(&dev->dev.kobj, &dev->data);
      
      end:
              return result;
      }
      
      /**
       * acpi_device_remove_files - Remove sysfs attributes of an ACPI device.
       * @dev: ACPI device object.
       */
      void acpi_device_remove_files(struct acpi_device *dev)
      {
              acpi_hide_nondev_subnodes(&dev->data);
      
              if (dev->flags.power_manageable) {
                      device_remove_file(&dev->dev, &dev_attr_power_state);
                      if (dev->power.flags.power_resources)
                              device_remove_file(&dev->dev,
                                                 &dev_attr_real_power_state);
              }
      
              /*
               * If device has _STR, remove 'description' file
               */
              if (acpi_has_method(dev->handle, "_STR")) {
                      kfree(dev->pnp.str_obj);
                      device_remove_file(&dev->dev, &dev_attr_description);
              }
              /*
               * If device has _EJ0, remove 'eject' file.
               */
              if (acpi_has_method(dev->handle, "_EJ0"))
                      device_remove_file(&dev->dev, &dev_attr_eject);
      
              if (acpi_has_method(dev->handle, "_SUN"))
                      device_remove_file(&dev->dev, &dev_attr_sun);
      
              if (acpi_has_method(dev->handle, "_HRV"))
                      device_remove_file(&dev->dev, &dev_attr_hrv);
      
              if (dev->pnp.unique_id)
                      device_remove_file(&dev->dev, &dev_attr_uid);
              if (dev->pnp.type.bus_address)
                      device_remove_file(&dev->dev, &dev_attr_adr);
              device_remove_file(&dev->dev, &dev_attr_modalias);
              device_remove_file(&dev->dev, &dev_attr_hid);
              if (acpi_has_method(dev->handle, "_STA"))
                      device_remove_file(&dev->dev, &dev_attr_status);
              if (dev->handle)
                      device_remove_file(&dev->dev, &dev_attr_path);
      }
      // SPDX-License-Identifier: GPL-2.0-only
      /*
       * fs/kernfs/dir.c - kernfs directory implementation
       *
       * Copyright (c) 2001-3 Patrick Mochel
       * Copyright (c) 2007 SUSE Linux Products GmbH
       * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org>
       */
      
      #include <linux/sched.h>
      #include <linux/fs.h>
      #include <linux/namei.h>
      #include <linux/idr.h>
      #include <linux/slab.h>
      #include <linux/security.h>
      #include <linux/hash.h>
      
      #include "kernfs-internal.h"
      
      DEFINE_MUTEX(kernfs_mutex);
      static DEFINE_SPINLOCK(kernfs_rename_lock);        /* kn->parent and ->name */
      static char kernfs_pr_cont_buf[PATH_MAX];        /* protected by rename_lock */
      static DEFINE_SPINLOCK(kernfs_idr_lock);        /* root->ino_idr */
      
      #define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb)
      
      static bool kernfs_active(struct kernfs_node *kn)
      {
 1714         lockdep_assert_held(&kernfs_mutex);
 1714         return atomic_read(&kn->active) >= 0;
      }
      
      static bool kernfs_lockdep(struct kernfs_node *kn)
      {
      #ifdef CONFIG_DEBUG_LOCK_ALLOC
              return kn->flags & KERNFS_LOCKDEP;
      #else
              return false;
      #endif
      }
      
      static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen)
      {
              if (!kn)
                      return strlcpy(buf, "(null)", buflen);
      
              return strlcpy(buf, kn->parent ? kn->name : "/", buflen);
      }
      
      /* kernfs_node_depth - compute depth from @from to @to */
      static size_t kernfs_depth(struct kernfs_node *from, struct kernfs_node *to)
      {
              size_t depth = 0;
      
              while (to->parent && to != from) {
                      depth++;
                      to = to->parent;
              }
              return depth;
      }
      
      static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a,
                                                        struct kernfs_node *b)
      {
              size_t da, db;
              struct kernfs_root *ra = kernfs_root(a), *rb = kernfs_root(b);
      
              if (ra != rb)
                      return NULL;
      
              da = kernfs_depth(ra->kn, a);
              db = kernfs_depth(rb->kn, b);
      
              while (da > db) {
                      a = a->parent;
                      da--;
              }
              while (db > da) {
                      b = b->parent;
                      db--;
              }
      
              /* worst case b and a will be the same at root */
              while (b != a) {
                      b = b->parent;
                      a = a->parent;
              }
      
              return a;
      }
      
      /**
       * kernfs_path_from_node_locked - find a pseudo-absolute path to @kn_to,
       * where kn_from is treated as root of the path.
       * @kn_from: kernfs node which should be treated as root for the path
       * @kn_to: kernfs node to which path is needed
       * @buf: buffer to copy the path into
       * @buflen: size of @buf
       *
       * We need to handle couple of scenarios here:
       * [1] when @kn_from is an ancestor of @kn_to at some level
       * kn_from: /n1/n2/n3
       * kn_to:   /n1/n2/n3/n4/n5
       * result:  /n4/n5
       *
       * [2] when @kn_from is on a different hierarchy and we need to find common
       * ancestor between @kn_from and @kn_to.
       * kn_from: /n1/n2/n3/n4
       * kn_to:   /n1/n2/n5
       * result:  /../../n5
       * OR
       * kn_from: /n1/n2/n3/n4/n5   [depth=5]
       * kn_to:   /n1/n2/n3         [depth=3]
       * result:  /../..
       *
       * [3] when @kn_to is NULL result will be "(null)"
       *
       * Returns the length of the full path.  If the full length is equal to or
       * greater than @buflen, @buf contains the truncated path with the trailing
       * '\0'.  On error, -errno is returned.
       */
      static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
                                              struct kernfs_node *kn_from,
                                              char *buf, size_t buflen)
      {
              struct kernfs_node *kn, *common;
              const char parent_str[] = "/..";
              size_t depth_from, depth_to, len = 0;
              int i, j;
      
              if (!kn_to)
                      return strlcpy(buf, "(null)", buflen);
      
              if (!kn_from)
                      kn_from = kernfs_root(kn_to)->kn;
      
              if (kn_from == kn_to)
                      return strlcpy(buf, "/", buflen);
      
              if (!buf)
                      return -EINVAL;
      
              common = kernfs_common_ancestor(kn_from, kn_to);
              if (WARN_ON(!common))
                      return -EINVAL;
      
              depth_to = kernfs_depth(common, kn_to);
              depth_from = kernfs_depth(common, kn_from);
      
              buf[0] = '\0';
      
              for (i = 0; i < depth_from; i++)
                      len += strlcpy(buf + len, parent_str,
                                     len < buflen ? buflen - len : 0);
      
              /* Calculate how many bytes we need for the rest */
              for (i = depth_to - 1; i >= 0; i--) {
                      for (kn = kn_to, j = 0; j < i; j++)
                              kn = kn->parent;
                      len += strlcpy(buf + len, "/",
                                     len < buflen ? buflen - len : 0);
                      len += strlcpy(buf + len, kn->name,
                                     len < buflen ? buflen - len : 0);
              }
      
              return len;
      }
      
      /**
       * kernfs_name - obtain the name of a given node
       * @kn: kernfs_node of interest
       * @buf: buffer to copy @kn's name into
       * @buflen: size of @buf
       *
       * Copies the name of @kn into @buf of @buflen bytes.  The behavior is
       * similar to strlcpy().  It returns the length of @kn's name and if @buf
       * isn't long enough, it's filled upto @buflen-1 and nul terminated.
       *
       * Fills buffer with "(null)" if @kn is NULL.
       *
       * This function can be called from any context.
       */
      int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
      {
              unsigned long flags;
              int ret;
      
              spin_lock_irqsave(&kernfs_rename_lock, flags);
              ret = kernfs_name_locked(kn, buf, buflen);
              spin_unlock_irqrestore(&kernfs_rename_lock, flags);
              return ret;
      }
      
      /**
       * kernfs_path_from_node - build path of node @to relative to @from.
       * @from: parent kernfs_node relative to which we need to build the path
       * @to: kernfs_node of interest
       * @buf: buffer to copy @to's path into
       * @buflen: size of @buf
       *
       * Builds @to's path relative to @from in @buf. @from and @to must
       * be on the same kernfs-root. If @from is not parent of @to, then a relative
       * path (which includes '..'s) as needed to reach from @from to @to is
       * returned.
       *
       * Returns the length of the full path.  If the full length is equal to or
       * greater than @buflen, @buf contains the truncated path with the trailing
       * '\0'.  On error, -errno is returned.
       */
      int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from,
                                char *buf, size_t buflen)
      {
              unsigned long flags;
              int ret;
      
              spin_lock_irqsave(&kernfs_rename_lock, flags);
              ret = kernfs_path_from_node_locked(to, from, buf, buflen);
              spin_unlock_irqrestore(&kernfs_rename_lock, flags);
              return ret;
      }
      EXPORT_SYMBOL_GPL(kernfs_path_from_node);
      
      /**
       * pr_cont_kernfs_name - pr_cont name of a kernfs_node
       * @kn: kernfs_node of interest
       *
       * This function can be called from any context.
       */
      void pr_cont_kernfs_name(struct kernfs_node *kn)
      {
              unsigned long flags;
      
              spin_lock_irqsave(&kernfs_rename_lock, flags);
      
              kernfs_name_locked(kn, kernfs_pr_cont_buf, sizeof(kernfs_pr_cont_buf));
              pr_cont("%s", kernfs_pr_cont_buf);
      
              spin_unlock_irqrestore(&kernfs_rename_lock, flags);
      }
      
      /**
       * pr_cont_kernfs_path - pr_cont path of a kernfs_node
       * @kn: kernfs_node of interest
       *
       * This function can be called from any context.
       */
      void pr_cont_kernfs_path(struct kernfs_node *kn)
      {
              unsigned long flags;
              int sz;
      
              spin_lock_irqsave(&kernfs_rename_lock, flags);
      
              sz = kernfs_path_from_node_locked(kn, NULL, kernfs_pr_cont_buf,
                                                sizeof(kernfs_pr_cont_buf));
              if (sz < 0) {
                      pr_cont("(error)");
                      goto out;
              }
      
              if (sz >= sizeof(kernfs_pr_cont_buf)) {
                      pr_cont("(name too long)");
                      goto out;
              }
      
              pr_cont("%s", kernfs_pr_cont_buf);
      
      out:
              spin_unlock_irqrestore(&kernfs_rename_lock, flags);
      }
      
      /**
       * kernfs_get_parent - determine the parent node and pin it
       * @kn: kernfs_node of interest
       *
       * Determines @kn's parent, pins and returns it.  This function can be
       * called from any context.
       */
      struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
      {
              struct kernfs_node *parent;
              unsigned long flags;
      
              spin_lock_irqsave(&kernfs_rename_lock, flags);
              parent = kn->parent;
              kernfs_get(parent);
              spin_unlock_irqrestore(&kernfs_rename_lock, flags);
      
              return parent;