refcount_inc(&req->refs);
 }
 
+static int io_init_wq_offload(struct io_ring_ctx *ctx,
+                             struct io_uring_params *p)
+{
+       struct io_wq_data data;
+       struct fd f;
+       struct io_ring_ctx *ctx_attach;
+       unsigned int concurrency;
+       int ret = 0;
+
+       data.user = ctx->user;
+       data.get_work = io_get_work;
+       data.put_work = io_put_work;
+
+       if (!(p->flags & IORING_SETUP_ATTACH_WQ)) {
+               /* Do QD, or 4 * CPUS, whatever is smallest */
+               concurrency = min(ctx->sq_entries, 4 * num_online_cpus());
+
+               ctx->io_wq = io_wq_create(concurrency, &data);
+               if (IS_ERR(ctx->io_wq)) {
+                       ret = PTR_ERR(ctx->io_wq);
+                       ctx->io_wq = NULL;
+               }
+               return ret;
+       }
+
+       f = fdget(p->wq_fd);
+       if (!f.file)
+               return -EBADF;
+
+       if (f.file->f_op != &io_uring_fops) {
+               ret = -EINVAL;
+               goto out_fput;
+       }
+
+       ctx_attach = f.file->private_data;
+       /* @io_wq is protected by holding the fd */
+       if (!io_wq_get(ctx_attach->io_wq, &data)) {
+               ret = -EINVAL;
+               goto out_fput;
+       }
+
+       ctx->io_wq = ctx_attach->io_wq;
+out_fput:
+       fdput(f);
+       return ret;
+}
+
 static int io_sq_offload_start(struct io_ring_ctx *ctx,
                               struct io_uring_params *p)
 {
-       struct io_wq_data data;
-       unsigned concurrency;
        int ret;
 
        init_waitqueue_head(&ctx->sqo_wait);
                goto err;
        }
 
-       data.user = ctx->user;
-       data.get_work = io_get_work;
-       data.put_work = io_put_work;
-
-       /* Do QD, or 4 * CPUS, whatever is smallest */
-       concurrency = min(ctx->sq_entries, 4 * num_online_cpus());
-       ctx->io_wq = io_wq_create(concurrency, &data);
-       if (IS_ERR(ctx->io_wq)) {
-               ret = PTR_ERR(ctx->io_wq);
-               ctx->io_wq = NULL;
+       ret = io_init_wq_offload(ctx, p);
+       if (ret)
                goto err;
-       }
 
        return 0;
 err:
 
        if (p.flags & ~(IORING_SETUP_IOPOLL | IORING_SETUP_SQPOLL |
                        IORING_SETUP_SQ_AFF | IORING_SETUP_CQSIZE |
-                       IORING_SETUP_CLAMP))
+                       IORING_SETUP_CLAMP | IORING_SETUP_ATTACH_WQ))
                return -EINVAL;
 
        ret = io_uring_create(entries, &p);