static int copy_io(unsigned long clone_flags, struct task_struct *tsk)
{
#ifdef CONFIG_BLOCK
 struct io_context *ioc = current->io_context;
 struct io_context *new_ioc;
 if (!ioc)
  return 0;
 /*
  * Share io context with parent, if CLONE_IO is set
  */
 if (clone_flags & CLONE_IO) {
  ioc_task_link(ioc);
  tsk->io_context = ioc;
 } else if (ioprio_valid(ioc->ioprio)) {
  new_ioc = get_task_io_context(tsk, GFP_KERNEL, NUMA_NO_NODE);
  if (unlikely(!new_ioc))
   return -ENOMEM;
  new_ioc->ioprio = ioc->ioprio;
  put_io_context(new_ioc);
 }
#endif
 return 0;
}


/**
 * get_task_io_context - get io_context of a task
 * @task: task of interest
 * @gfp_flags: allocation flags, used if allocation is necessary
 * @node: allocation node, used if allocation is necessary
 *
 * Return io_context of @task.  If it doesn't exist, it is created with
 * @gfp_flags and @node.  The returned io_context has its reference count
 * incremented.
 *
 * This function always goes through task_lock() and it's better to use
 * %current->io_context + get_io_context() for %current.
 */
struct io_context *get_task_io_context(struct task_struct *task,
           gfp_t gfp_flags, int node)
{
 struct io_context *ioc;
 might_sleep_if(gfpflags_allow_blocking(gfp_flags));
 do {
  task_lock(task);
  ioc = task->io_context;
  if (likely(ioc)) {
   get_io_context(ioc);
   task_unlock(task);
   return ioc;
  }
  task_unlock(task);
 } while (!create_task_io_context(task, gfp_flags, node));
 return NULL;
}

int create_task_io_context(struct task_struct *task, gfp_t gfp_flags, int node)
{
 struct io_context *ioc;
 int ret;
 ioc = kmem_cache_alloc_node(iocontext_cachep, gfp_flags | __GFP_ZERO,
        node);
 if (unlikely(!ioc))
  return -ENOMEM;
 /* initialize */
 atomic_long_set(&ioc->refcount, 1);
 atomic_set(&ioc->nr_tasks, 1);
 atomic_set(&ioc->active_ref, 1);
 spin_lock_init(&ioc->lock);
 INIT_RADIX_TREE(&ioc->icq_tree, GFP_ATOMIC | __GFP_HIGH);
 INIT_HLIST_HEAD(&ioc->icq_list);
 INIT_WORK(&ioc->release_work, ioc_release_fn);
 /*
  * Try to install.  ioc shouldn't be installed if someone else
  * already did or @task, which isn't %current, is exiting.  Note
  * that we need to allow ioc creation on exiting %current as exit
  * path may issue IOs from e.g. exit_files().  The exit path is
  * responsible for not issuing IO after exit_io_context().
  */
 task_lock(task);
 if (!task->io_context &&
     (task == current || !(task->flags & PF_EXITING)))
  task->io_context = ioc;
 else
  kmem_cache_free(iocontext_cachep, ioc);
 ret = task->io_context ? 0 : -EBUSY;
 task_unlock(task);
 return ret;
}