1 // SPDX-License-Identifier: GPL-2.0 2 #ifndef NO_BCACHEFS_FS 3 4 #include "bcachefs.h" 5 #include "thread_with_file.h" 6 7 #include <linux/anon_inodes.h> 8 #include <linux/file.h> 9 #include <linux/kthread.h> 10 #include <linux/pagemap.h> 11 #include <linux/poll.h> 12 #include <linux/sched/sysctl.h> 13 14 void bch2_thread_with_file_exit(struct thread_with_file *thr) 15 { 16 if (thr->task) { 17 kthread_stop(thr->task); 18 put_task_struct(thr->task); 19 } 20 } 21 22 int bch2_run_thread_with_file(struct thread_with_file *thr, 23 const struct file_operations *fops, 24 int (*fn)(void *)) 25 { 26 struct file *file = NULL; 27 int ret, fd = -1; 28 unsigned fd_flags = O_CLOEXEC; 29 30 if (fops->read && fops->write) 31 fd_flags |= O_RDWR; 32 else if (fops->read) 33 fd_flags |= O_RDONLY; 34 else if (fops->write) 35 fd_flags |= O_WRONLY; 36 37 char name[TASK_COMM_LEN]; 38 get_task_comm(name, current); 39 40 thr->ret = 0; 41 thr->task = kthread_create(fn, thr, "%s", name); 42 ret = PTR_ERR_OR_ZERO(thr->task); 43 if (ret) 44 return ret; 45 46 ret = get_unused_fd_flags(fd_flags); 47 if (ret < 0) 48 goto err; 49 fd = ret; 50 51 file = anon_inode_getfile(name, fops, thr, fd_flags); 52 ret = PTR_ERR_OR_ZERO(file); 53 if (ret) 54 goto err; 55 56 get_task_struct(thr->task); 57 wake_up_process(thr->task); 58 fd_install(fd, file); 59 return fd; 60 err: 61 if (fd >= 0) 62 put_unused_fd(fd); 63 if (thr->task) 64 kthread_stop(thr->task); 65 return ret; 66 } 67 68 /* stdio_redirect */ 69 70 static bool stdio_redirect_has_input(struct stdio_redirect *stdio) 71 { 72 return stdio->input.buf.nr || stdio->done; 73 } 74 75 static bool stdio_redirect_has_output(struct stdio_redirect *stdio) 76 { 77 return stdio->output.buf.nr || stdio->done; 78 } 79 80 #define STDIO_REDIRECT_BUFSIZE 4096 81 82 static bool stdio_redirect_has_input_space(struct stdio_redirect *stdio) 83 { 84 return stdio->input.buf.nr < STDIO_REDIRECT_BUFSIZE || stdio->done; 85 } 86 87 static bool stdio_redirect_has_output_space(struct stdio_redirect *stdio) 88 { 89 return stdio->output.buf.nr < STDIO_REDIRECT_BUFSIZE || stdio->done; 90 } 91 92 static void stdio_buf_init(struct stdio_buf *buf) 93 { 94 spin_lock_init(&buf->lock); 95 init_waitqueue_head(&buf->wait); 96 darray_init(&buf->buf); 97 } 98 99 /* thread_with_stdio */ 100 101 static void thread_with_stdio_done(struct thread_with_stdio *thr) 102 { 103 thr->thr.done = true; 104 thr->stdio.done = true; 105 wake_up(&thr->stdio.input.wait); 106 wake_up(&thr->stdio.output.wait); 107 } 108 109 static ssize_t thread_with_stdio_read(struct file *file, char __user *ubuf, 110 size_t len, loff_t *ppos) 111 { 112 struct thread_with_stdio *thr = 113 container_of(file->private_data, struct thread_with_stdio, thr); 114 struct stdio_buf *buf = &thr->stdio.output; 115 size_t copied = 0, b; 116 int ret = 0; 117 118 if (!(file->f_flags & O_NONBLOCK)) { 119 ret = wait_event_interruptible(buf->wait, stdio_redirect_has_output(&thr->stdio)); 120 if (ret) 121 return ret; 122 } else if (!stdio_redirect_has_output(&thr->stdio)) 123 return -EAGAIN; 124 125 while (len && buf->buf.nr) { 126 if (fault_in_writeable(ubuf, len) == len) { 127 ret = -EFAULT; 128 break; 129 } 130 131 spin_lock_irq(&buf->lock); 132 b = min_t(size_t, len, buf->buf.nr); 133 134 if (b && !copy_to_user_nofault(ubuf, buf->buf.data, b)) { 135 ubuf += b; 136 len -= b; 137 copied += b; 138 buf->buf.nr -= b; 139 memmove(buf->buf.data, 140 buf->buf.data + b, 141 buf->buf.nr); 142 } 143 spin_unlock_irq(&buf->lock); 144 } 145 146 return copied ?: ret; 147 } 148 149 static int thread_with_stdio_release(struct inode *inode, struct file *file) 150 { 151 struct thread_with_stdio *thr = 152 container_of(file->private_data, struct thread_with_stdio, thr); 153 154 thread_with_stdio_done(thr); 155 bch2_thread_with_file_exit(&thr->thr); 156 darray_exit(&thr->stdio.input.buf); 157 darray_exit(&thr->stdio.output.buf); 158 thr->ops->exit(thr); 159 return 0; 160 } 161 162 static ssize_t thread_with_stdio_write(struct file *file, const char __user *ubuf, 163 size_t len, loff_t *ppos) 164 { 165 struct thread_with_stdio *thr = 166 container_of(file->private_data, struct thread_with_stdio, thr); 167 struct stdio_buf *buf = &thr->stdio.input; 168 size_t copied = 0; 169 ssize_t ret = 0; 170 171 while (len) { 172 if (thr->thr.done) { 173 ret = -EPIPE; 174 break; 175 } 176 177 size_t b = len - fault_in_readable(ubuf, len); 178 if (!b) { 179 ret = -EFAULT; 180 break; 181 } 182 183 spin_lock(&buf->lock); 184 if (buf->buf.nr < STDIO_REDIRECT_BUFSIZE) 185 darray_make_room_gfp(&buf->buf, 186 min(b, STDIO_REDIRECT_BUFSIZE - buf->buf.nr), GFP_NOWAIT); 187 b = min(len, darray_room(buf->buf)); 188 189 if (b && !copy_from_user_nofault(&darray_top(buf->buf), ubuf, b)) { 190 buf->buf.nr += b; 191 ubuf += b; 192 len -= b; 193 copied += b; 194 } 195 spin_unlock(&buf->lock); 196 197 if (b) { 198 wake_up(&buf->wait); 199 } else { 200 if ((file->f_flags & O_NONBLOCK)) { 201 ret = -EAGAIN; 202 break; 203 } 204 205 ret = wait_event_interruptible(buf->wait, 206 stdio_redirect_has_input_space(&thr->stdio)); 207 if (ret) 208 break; 209 } 210 } 211 212 return copied ?: ret; 213 } 214 215 static __poll_t thread_with_stdio_poll(struct file *file, struct poll_table_struct *wait) 216 { 217 struct thread_with_stdio *thr = 218 container_of(file->private_data, struct thread_with_stdio, thr); 219 220 poll_wait(file, &thr->stdio.output.wait, wait); 221 poll_wait(file, &thr->stdio.input.wait, wait); 222 223 __poll_t mask = 0; 224 225 if (stdio_redirect_has_output(&thr->stdio)) 226 mask |= EPOLLIN; 227 if (stdio_redirect_has_input_space(&thr->stdio)) 228 mask |= EPOLLOUT; 229 if (thr->thr.done) 230 mask |= EPOLLHUP|EPOLLERR; 231 return mask; 232 } 233 234 static __poll_t thread_with_stdout_poll(struct file *file, struct poll_table_struct *wait) 235 { 236 struct thread_with_stdio *thr = 237 container_of(file->private_data, struct thread_with_stdio, thr); 238 239 poll_wait(file, &thr->stdio.output.wait, wait); 240 241 __poll_t mask = 0; 242 243 if (stdio_redirect_has_output(&thr->stdio)) 244 mask |= EPOLLIN; 245 if (thr->thr.done) 246 mask |= EPOLLHUP|EPOLLERR; 247 return mask; 248 } 249 250 static int thread_with_stdio_flush(struct file *file, fl_owner_t id) 251 { 252 struct thread_with_stdio *thr = 253 container_of(file->private_data, struct thread_with_stdio, thr); 254 255 return thr->thr.ret; 256 } 257 258 static long thread_with_stdio_ioctl(struct file *file, unsigned int cmd, unsigned long p) 259 { 260 struct thread_with_stdio *thr = 261 container_of(file->private_data, struct thread_with_stdio, thr); 262 263 if (thr->ops->unlocked_ioctl) 264 return thr->ops->unlocked_ioctl(thr, cmd, p); 265 return -ENOTTY; 266 } 267 268 static const struct file_operations thread_with_stdio_fops = { 269 .llseek = no_llseek, 270 .read = thread_with_stdio_read, 271 .write = thread_with_stdio_write, 272 .poll = thread_with_stdio_poll, 273 .flush = thread_with_stdio_flush, 274 .release = thread_with_stdio_release, 275 .unlocked_ioctl = thread_with_stdio_ioctl, 276 }; 277 278 static const struct file_operations thread_with_stdout_fops = { 279 .llseek = no_llseek, 280 .read = thread_with_stdio_read, 281 .poll = thread_with_stdout_poll, 282 .flush = thread_with_stdio_flush, 283 .release = thread_with_stdio_release, 284 .unlocked_ioctl = thread_with_stdio_ioctl, 285 }; 286 287 static int thread_with_stdio_fn(void *arg) 288 { 289 struct thread_with_stdio *thr = arg; 290 291 thr->thr.ret = thr->ops->fn(thr); 292 293 thread_with_stdio_done(thr); 294 return 0; 295 } 296 297 int bch2_run_thread_with_stdio(struct thread_with_stdio *thr, 298 const struct thread_with_stdio_ops *ops) 299 { 300 stdio_buf_init(&thr->stdio.input); 301 stdio_buf_init(&thr->stdio.output); 302 thr->ops = ops; 303 304 return bch2_run_thread_with_file(&thr->thr, &thread_with_stdio_fops, thread_with_stdio_fn); 305 } 306 307 int bch2_run_thread_with_stdout(struct thread_with_stdio *thr, 308 const struct thread_with_stdio_ops *ops) 309 { 310 stdio_buf_init(&thr->stdio.input); 311 stdio_buf_init(&thr->stdio.output); 312 thr->ops = ops; 313 314 return bch2_run_thread_with_file(&thr->thr, &thread_with_stdout_fops, thread_with_stdio_fn); 315 } 316 EXPORT_SYMBOL_GPL(bch2_run_thread_with_stdout); 317 318 int bch2_stdio_redirect_read(struct stdio_redirect *stdio, char *ubuf, size_t len) 319 { 320 struct stdio_buf *buf = &stdio->input; 321 322 /* 323 * we're waiting on user input (or for the file descriptor to be 324 * closed), don't want a hung task warning: 325 */ 326 do { 327 wait_event_timeout(buf->wait, stdio_redirect_has_input(stdio), 328 sysctl_hung_task_timeout_secs * HZ / 2); 329 } while (!stdio_redirect_has_input(stdio)); 330 331 if (stdio->done) 332 return -1; 333 334 spin_lock(&buf->lock); 335 int ret = min(len, buf->buf.nr); 336 buf->buf.nr -= ret; 337 memcpy(ubuf, buf->buf.data, ret); 338 memmove(buf->buf.data, 339 buf->buf.data + ret, 340 buf->buf.nr); 341 spin_unlock(&buf->lock); 342 343 wake_up(&buf->wait); 344 return ret; 345 } 346 347 int bch2_stdio_redirect_readline(struct stdio_redirect *stdio, char *ubuf, size_t len) 348 { 349 struct stdio_buf *buf = &stdio->input; 350 size_t copied = 0; 351 ssize_t ret = 0; 352 again: 353 do { 354 wait_event_timeout(buf->wait, stdio_redirect_has_input(stdio), 355 sysctl_hung_task_timeout_secs * HZ / 2); 356 } while (!stdio_redirect_has_input(stdio)); 357 358 if (stdio->done) { 359 ret = -1; 360 goto out; 361 } 362 363 spin_lock(&buf->lock); 364 size_t b = min(len, buf->buf.nr); 365 char *n = memchr(buf->buf.data, '\n', b); 366 if (n) 367 b = min_t(size_t, b, n + 1 - buf->buf.data); 368 buf->buf.nr -= b; 369 memcpy(ubuf, buf->buf.data, b); 370 memmove(buf->buf.data, 371 buf->buf.data + b, 372 buf->buf.nr); 373 ubuf += b; 374 len -= b; 375 copied += b; 376 spin_unlock(&buf->lock); 377 378 wake_up(&buf->wait); 379 380 if (!n && len) 381 goto again; 382 out: 383 return copied ?: ret; 384 } 385 386 __printf(3, 0) 387 static ssize_t bch2_darray_vprintf(darray_char *out, gfp_t gfp, const char *fmt, va_list args) 388 { 389 ssize_t ret; 390 391 do { 392 va_list args2; 393 size_t len; 394 395 va_copy(args2, args); 396 len = vsnprintf(out->data + out->nr, darray_room(*out), fmt, args2); 397 va_end(args2); 398 399 if (len + 1 <= darray_room(*out)) { 400 out->nr += len; 401 return len; 402 } 403 404 ret = darray_make_room_gfp(out, len + 1, gfp); 405 } while (ret == 0); 406 407 return ret; 408 } 409 410 ssize_t bch2_stdio_redirect_vprintf(struct stdio_redirect *stdio, bool nonblocking, 411 const char *fmt, va_list args) 412 { 413 struct stdio_buf *buf = &stdio->output; 414 unsigned long flags; 415 ssize_t ret; 416 417 again: 418 spin_lock_irqsave(&buf->lock, flags); 419 ret = bch2_darray_vprintf(&buf->buf, GFP_NOWAIT, fmt, args); 420 spin_unlock_irqrestore(&buf->lock, flags); 421 422 if (ret < 0) { 423 if (nonblocking) 424 return -EAGAIN; 425 426 ret = wait_event_interruptible(buf->wait, 427 stdio_redirect_has_output_space(stdio)); 428 if (ret) 429 return ret; 430 goto again; 431 } 432 433 wake_up(&buf->wait); 434 return ret; 435 } 436 437 ssize_t bch2_stdio_redirect_printf(struct stdio_redirect *stdio, bool nonblocking, 438 const char *fmt, ...) 439 { 440 va_list args; 441 ssize_t ret; 442 443 va_start(args, fmt); 444 ret = bch2_stdio_redirect_vprintf(stdio, nonblocking, fmt, args); 445 va_end(args); 446 447 return ret; 448 } 449 450 #endif /* NO_BCACHEFS_FS */ 451