]>
git.ipfire.org Git - thirdparty/linux.git/blob - io_uring/fdinfo.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
5 #include <linux/file.h>
6 #include <linux/proc_fs.h>
7 #include <linux/seq_file.h>
8 #include <linux/io_uring.h>
10 #include <uapi/linux/io_uring.h>
19 static __cold
int io_uring_show_cred(struct seq_file
*m
, unsigned int id
,
20 const struct cred
*cred
)
22 struct user_namespace
*uns
= seq_user_ns(m
);
23 struct group_info
*gi
;
27 seq_printf(m
, "%5d\n", id
);
28 seq_put_decimal_ull(m
, "\tUid:\t", from_kuid_munged(uns
, cred
->uid
));
29 seq_put_decimal_ull(m
, "\t\t", from_kuid_munged(uns
, cred
->euid
));
30 seq_put_decimal_ull(m
, "\t\t", from_kuid_munged(uns
, cred
->suid
));
31 seq_put_decimal_ull(m
, "\t\t", from_kuid_munged(uns
, cred
->fsuid
));
32 seq_put_decimal_ull(m
, "\n\tGid:\t", from_kgid_munged(uns
, cred
->gid
));
33 seq_put_decimal_ull(m
, "\t\t", from_kgid_munged(uns
, cred
->egid
));
34 seq_put_decimal_ull(m
, "\t\t", from_kgid_munged(uns
, cred
->sgid
));
35 seq_put_decimal_ull(m
, "\t\t", from_kgid_munged(uns
, cred
->fsgid
));
36 seq_puts(m
, "\n\tGroups:\t");
37 gi
= cred
->group_info
;
38 for (g
= 0; g
< gi
->ngroups
; g
++) {
39 seq_put_decimal_ull(m
, g
? " " : "",
40 from_kgid_munged(uns
, gi
->gid
[g
]));
42 seq_puts(m
, "\n\tCapEff:\t");
43 cap
= cred
->cap_effective
;
44 seq_put_hex_ll(m
, NULL
, cap
.val
, 16);
49 static __cold
void __io_uring_show_fdinfo(struct io_ring_ctx
*ctx
,
52 struct io_sq_data
*sq
= NULL
;
53 struct io_overflow_cqe
*ocqe
;
54 struct io_rings
*r
= ctx
->rings
;
55 unsigned int sq_mask
= ctx
->sq_entries
- 1, cq_mask
= ctx
->cq_entries
- 1;
56 unsigned int sq_head
= READ_ONCE(r
->sq
.head
);
57 unsigned int sq_tail
= READ_ONCE(r
->sq
.tail
);
58 unsigned int cq_head
= READ_ONCE(r
->cq
.head
);
59 unsigned int cq_tail
= READ_ONCE(r
->cq
.tail
);
60 unsigned int cq_shift
= 0;
61 unsigned int sq_shift
= 0;
62 unsigned int sq_entries
, cq_entries
;
66 if (ctx
->flags
& IORING_SETUP_CQE32
)
68 if (ctx
->flags
& IORING_SETUP_SQE128
)
72 * we may get imprecise sqe and cqe info if uring is actively running
73 * since we get cached_sq_head and cached_cq_tail without uring_lock
74 * and sq_tail and cq_head are changed by userspace. But it's ok since
75 * we usually use these info when it is stuck.
77 seq_printf(m
, "SqMask:\t0x%x\n", sq_mask
);
78 seq_printf(m
, "SqHead:\t%u\n", sq_head
);
79 seq_printf(m
, "SqTail:\t%u\n", sq_tail
);
80 seq_printf(m
, "CachedSqHead:\t%u\n", ctx
->cached_sq_head
);
81 seq_printf(m
, "CqMask:\t0x%x\n", cq_mask
);
82 seq_printf(m
, "CqHead:\t%u\n", cq_head
);
83 seq_printf(m
, "CqTail:\t%u\n", cq_tail
);
84 seq_printf(m
, "CachedCqTail:\t%u\n", ctx
->cached_cq_tail
);
85 seq_printf(m
, "SQEs:\t%u\n", sq_tail
- sq_head
);
86 sq_entries
= min(sq_tail
- sq_head
, ctx
->sq_entries
);
87 for (i
= 0; i
< sq_entries
; i
++) {
88 unsigned int entry
= i
+ sq_head
;
89 struct io_uring_sqe
*sqe
;
92 sq_idx
= READ_ONCE(ctx
->sq_array
[entry
& sq_mask
]);
95 sqe
= &ctx
->sq_sqes
[sq_idx
<< sq_shift
];
96 seq_printf(m
, "%5u: opcode:%s, fd:%d, flags:%x, off:%llu, "
97 "addr:0x%llx, rw_flags:0x%x, buf_index:%d "
99 sq_idx
, io_uring_get_opcode(sqe
->opcode
), sqe
->fd
,
100 sqe
->flags
, (unsigned long long) sqe
->off
,
101 (unsigned long long) sqe
->addr
, sqe
->rw_flags
,
102 sqe
->buf_index
, sqe
->user_data
);
104 u64
*sqeb
= (void *) (sqe
+ 1);
105 int size
= sizeof(struct io_uring_sqe
) / sizeof(u64
);
108 for (j
= 0; j
< size
; j
++) {
109 seq_printf(m
, ", e%d:0x%llx", j
,
110 (unsigned long long) *sqeb
);
116 seq_printf(m
, "CQEs:\t%u\n", cq_tail
- cq_head
);
117 cq_entries
= min(cq_tail
- cq_head
, ctx
->cq_entries
);
118 for (i
= 0; i
< cq_entries
; i
++) {
119 unsigned int entry
= i
+ cq_head
;
120 struct io_uring_cqe
*cqe
= &r
->cqes
[(entry
& cq_mask
) << cq_shift
];
122 seq_printf(m
, "%5u: user_data:%llu, res:%d, flag:%x",
123 entry
& cq_mask
, cqe
->user_data
, cqe
->res
,
126 seq_printf(m
, ", extra1:%llu, extra2:%llu\n",
127 cqe
->big_cqe
[0], cqe
->big_cqe
[1]);
132 * Avoid ABBA deadlock between the seq lock and the io_uring mutex,
133 * since fdinfo case grabs it in the opposite direction of normal use
134 * cases. If we fail to get the lock, we just don't iterate any
135 * structures that could be going away outside the io_uring mutex.
137 has_lock
= mutex_trylock(&ctx
->uring_lock
);
139 if (has_lock
&& (ctx
->flags
& IORING_SETUP_SQPOLL
)) {
145 seq_printf(m
, "SqThread:\t%d\n", sq
? task_pid_nr(sq
->thread
) : -1);
146 seq_printf(m
, "SqThreadCpu:\t%d\n", sq
? task_cpu(sq
->thread
) : -1);
147 seq_printf(m
, "UserFiles:\t%u\n", ctx
->nr_user_files
);
148 for (i
= 0; has_lock
&& i
< ctx
->nr_user_files
; i
++) {
149 struct file
*f
= io_file_from_index(&ctx
->file_table
, i
);
152 seq_printf(m
, "%5u: %s\n", i
, file_dentry(f
)->d_iname
);
154 seq_printf(m
, "%5u: <none>\n", i
);
156 seq_printf(m
, "UserBufs:\t%u\n", ctx
->nr_user_bufs
);
157 for (i
= 0; has_lock
&& i
< ctx
->nr_user_bufs
; i
++) {
158 struct io_mapped_ubuf
*buf
= ctx
->user_bufs
[i
];
159 unsigned int len
= buf
->ubuf_end
- buf
->ubuf
;
161 seq_printf(m
, "%5u: 0x%llx/%u\n", i
, buf
->ubuf
, len
);
163 if (has_lock
&& !xa_empty(&ctx
->personalities
)) {
165 const struct cred
*cred
;
167 seq_printf(m
, "Personalities:\n");
168 xa_for_each(&ctx
->personalities
, index
, cred
)
169 io_uring_show_cred(m
, index
, cred
);
172 seq_puts(m
, "PollList:\n");
173 for (i
= 0; i
< (1U << ctx
->cancel_table
.hash_bits
); i
++) {
174 struct io_hash_bucket
*hb
= &ctx
->cancel_table
.hbs
[i
];
175 struct io_hash_bucket
*hbl
= &ctx
->cancel_table_locked
.hbs
[i
];
176 struct io_kiocb
*req
;
178 spin_lock(&hb
->lock
);
179 hlist_for_each_entry(req
, &hb
->list
, hash_node
)
180 seq_printf(m
, " op=%d, task_works=%d\n", req
->opcode
,
181 task_work_pending(req
->task
));
182 spin_unlock(&hb
->lock
);
186 hlist_for_each_entry(req
, &hbl
->list
, hash_node
)
187 seq_printf(m
, " op=%d, task_works=%d\n", req
->opcode
,
188 task_work_pending(req
->task
));
192 mutex_unlock(&ctx
->uring_lock
);
194 seq_puts(m
, "CqOverflowList:\n");
195 spin_lock(&ctx
->completion_lock
);
196 list_for_each_entry(ocqe
, &ctx
->cq_overflow_list
, list
) {
197 struct io_uring_cqe
*cqe
= &ocqe
->cqe
;
199 seq_printf(m
, " user_data=%llu, res=%d, flags=%x\n",
200 cqe
->user_data
, cqe
->res
, cqe
->flags
);
204 spin_unlock(&ctx
->completion_lock
);
207 __cold
void io_uring_show_fdinfo(struct seq_file
*m
, struct file
*f
)
209 struct io_ring_ctx
*ctx
= f
->private_data
;
211 if (percpu_ref_tryget(&ctx
->refs
)) {
212 __io_uring_show_fdinfo(ctx
, m
);
213 percpu_ref_put(&ctx
->refs
);