interrupt.cc (d26d63a4af4f693b23f5ac389cc6e0d8938cd96b) | interrupt.cc (ed74f781c9f704092556f860a00b0bb53fdedff7) |
---|---|
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2019 The FreeBSD Foundation 5 * 6 * This software was developed by BFF Storage Systems, LLC under sponsorship 7 * from the FreeBSD Foundation. 8 * --- 171 unchanged lines hidden (view full) --- 180 181 sem_destroy(blocked_semaphore); 182 munmap(blocked_semaphore, sizeof(*blocked_semaphore)); 183 184 FuseTest::TearDown(); 185} 186}; 187 | 1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2019 The FreeBSD Foundation 5 * 6 * This software was developed by BFF Storage Systems, LLC under sponsorship 7 * from the FreeBSD Foundation. 8 * --- 171 unchanged lines hidden (view full) --- 180 181 sem_destroy(blocked_semaphore); 182 munmap(blocked_semaphore, sizeof(*blocked_semaphore)); 183 184 FuseTest::TearDown(); 185} 186}; 187 |
188class Intr: public Interrupt {}; 189 190class Nointr: public Interrupt { 191 void SetUp() { 192 m_nointr = true; 193 Interrupt::SetUp(); 194 } 195}; 196 |
|
188static void* mkdir0(void* arg __unused) { 189 ssize_t r; 190 191 r = mkdir(FULLDIRPATH0, MODE); 192 if (r >= 0) 193 return 0; 194 else 195 return (void*)(intptr_t)errno; --- 12 unchanged lines hidden (view full) --- 208 return (void*)(intptr_t)errno; 209} 210 211/* 212 * An interrupt operation that gets received after the original command is 213 * complete should generate an EAGAIN response. 214 */ 215/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ | 197static void* mkdir0(void* arg __unused) { 198 ssize_t r; 199 200 r = mkdir(FULLDIRPATH0, MODE); 201 if (r >= 0) 202 return 0; 203 else 204 return (void*)(intptr_t)errno; --- 12 unchanged lines hidden (view full) --- 217 return (void*)(intptr_t)errno; 218} 219 220/* 221 * An interrupt operation that gets received after the original command is 222 * complete should generate an EAGAIN response. 223 */ 224/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ |
216TEST_F(Interrupt, already_complete) | 225TEST_F(Intr, already_complete) |
217{ 218 uint64_t ino = 42; 219 pthread_t self; 220 uint64_t mkdir_unique = 0; 221 Sequence seq; 222 223 self = pthread_self(); 224 --- 41 unchanged lines hidden (view full) --- 266 EXPECT_EQ(0, access(FULLDIRPATH0, F_OK)) << strerror(errno); 267} 268 269/* 270 * If a FUSE file system returns ENOSYS for a FUSE_INTERRUPT operation, the 271 * kernel should not attempt to interrupt any other operations on that mount 272 * point. 273 */ | 226{ 227 uint64_t ino = 42; 228 pthread_t self; 229 uint64_t mkdir_unique = 0; 230 Sequence seq; 231 232 self = pthread_self(); 233 --- 41 unchanged lines hidden (view full) --- 275 EXPECT_EQ(0, access(FULLDIRPATH0, F_OK)) << strerror(errno); 276} 277 278/* 279 * If a FUSE file system returns ENOSYS for a FUSE_INTERRUPT operation, the 280 * kernel should not attempt to interrupt any other operations on that mount 281 * point. 282 */ |
274TEST_F(Interrupt, enosys) | 283TEST_F(Intr, enosys) |
275{ 276 uint64_t ino0 = 42, ino1 = 43;; 277 uint64_t mkdir_unique; 278 pthread_t self, th0; 279 sem_t sem0, sem1; 280 void *thr0_value; 281 Sequence seq; 282 --- 68 unchanged lines hidden (view full) --- 351 EXPECT_EQ(0, (intptr_t)thr0_value); 352} 353 354/* 355 * A FUSE filesystem is legally allowed to ignore INTERRUPT operations, and 356 * complete the original operation whenever it damn well pleases. 357 */ 358/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ | 284{ 285 uint64_t ino0 = 42, ino1 = 43;; 286 uint64_t mkdir_unique; 287 pthread_t self, th0; 288 sem_t sem0, sem1; 289 void *thr0_value; 290 Sequence seq; 291 --- 68 unchanged lines hidden (view full) --- 360 EXPECT_EQ(0, (intptr_t)thr0_value); 361} 362 363/* 364 * A FUSE filesystem is legally allowed to ignore INTERRUPT operations, and 365 * complete the original operation whenever it damn well pleases. 366 */ 367/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ |
359TEST_F(Interrupt, ignore) | 368TEST_F(Intr, ignore) |
360{ 361 uint64_t ino = 42; 362 pthread_t self; 363 uint64_t mkdir_unique; 364 365 self = pthread_self(); 366 367 EXPECT_LOOKUP(FUSE_ROOT_ID, RELDIRPATH0) --- 19 unchanged lines hidden (view full) --- 387 ASSERT_EQ(0, mkdir(FULLDIRPATH0, MODE)) << strerror(errno); 388} 389 390/* 391 * A restartable operation (basically, anything except write or setextattr) 392 * that hasn't yet been sent to userland can be interrupted without sending 393 * FUSE_INTERRUPT, and will be automatically restarted. 394 */ | 369{ 370 uint64_t ino = 42; 371 pthread_t self; 372 uint64_t mkdir_unique; 373 374 self = pthread_self(); 375 376 EXPECT_LOOKUP(FUSE_ROOT_ID, RELDIRPATH0) --- 19 unchanged lines hidden (view full) --- 396 ASSERT_EQ(0, mkdir(FULLDIRPATH0, MODE)) << strerror(errno); 397} 398 399/* 400 * A restartable operation (basically, anything except write or setextattr) 401 * that hasn't yet been sent to userland can be interrupted without sending 402 * FUSE_INTERRUPT, and will be automatically restarted. 403 */ |
395TEST_F(Interrupt, in_kernel_restartable) | 404TEST_F(Intr, in_kernel_restartable) |
396{ 397 const char FULLPATH1[] = "mountpoint/other_file.txt"; 398 const char RELPATH1[] = "other_file.txt"; 399 uint64_t ino0 = 42, ino1 = 43; 400 int fd1; 401 pthread_t self, th0, th1; 402 sem_t sem0, sem1; 403 void *thr0_value, *thr1_value; --- 53 unchanged lines hidden (view full) --- 457 sem_destroy(&sem0); 458} 459 460/* 461 * An operation that hasn't yet been sent to userland can be interrupted 462 * without sending FUSE_INTERRUPT. If it's a non-restartable operation (write 463 * or setextattr) it will return EINTR. 464 */ | 405{ 406 const char FULLPATH1[] = "mountpoint/other_file.txt"; 407 const char RELPATH1[] = "other_file.txt"; 408 uint64_t ino0 = 42, ino1 = 43; 409 int fd1; 410 pthread_t self, th0, th1; 411 sem_t sem0, sem1; 412 void *thr0_value, *thr1_value; --- 53 unchanged lines hidden (view full) --- 466 sem_destroy(&sem0); 467} 468 469/* 470 * An operation that hasn't yet been sent to userland can be interrupted 471 * without sending FUSE_INTERRUPT. If it's a non-restartable operation (write 472 * or setextattr) it will return EINTR. 473 */ |
465TEST_F(Interrupt, in_kernel_nonrestartable) | 474TEST_F(Intr, in_kernel_nonrestartable) |
466{ 467 const char FULLPATH1[] = "mountpoint/other_file.txt"; 468 const char RELPATH1[] = "other_file.txt"; 469 const char value[] = "whatever"; 470 ssize_t value_len = strlen(value) + 1; 471 uint64_t ino0 = 42, ino1 = 43; 472 int ns = EXTATTR_NAMESPACE_USER; 473 int fd1; --- 54 unchanged lines hidden (view full) --- 528 529/* 530 * A syscall that gets interrupted while blocking on FUSE I/O should send a 531 * FUSE_INTERRUPT command to the fuse filesystem, which should then send EINTR 532 * in response to the _original_ operation. The kernel should ultimately 533 * return EINTR to userspace 534 */ 535/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ | 475{ 476 const char FULLPATH1[] = "mountpoint/other_file.txt"; 477 const char RELPATH1[] = "other_file.txt"; 478 const char value[] = "whatever"; 479 ssize_t value_len = strlen(value) + 1; 480 uint64_t ino0 = 42, ino1 = 43; 481 int ns = EXTATTR_NAMESPACE_USER; 482 int fd1; --- 54 unchanged lines hidden (view full) --- 537 538/* 539 * A syscall that gets interrupted while blocking on FUSE I/O should send a 540 * FUSE_INTERRUPT command to the fuse filesystem, which should then send EINTR 541 * in response to the _original_ operation. The kernel should ultimately 542 * return EINTR to userspace 543 */ 544/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ |
536TEST_F(Interrupt, in_progress) | 545TEST_F(Intr, in_progress) |
537{ 538 pthread_t self; 539 uint64_t mkdir_unique; 540 541 self = pthread_self(); 542 543 EXPECT_LOOKUP(FUSE_ROOT_ID, RELDIRPATH0) 544 .WillOnce(Invoke(ReturnErrno(ENOENT))); --- 13 unchanged lines hidden (view full) --- 558 })); 559 560 setup_interruptor(self); 561 ASSERT_EQ(-1, mkdir(FULLDIRPATH0, MODE)); 562 EXPECT_EQ(EINTR, errno); 563} 564 565/* Reads should also be interruptible */ | 546{ 547 pthread_t self; 548 uint64_t mkdir_unique; 549 550 self = pthread_self(); 551 552 EXPECT_LOOKUP(FUSE_ROOT_ID, RELDIRPATH0) 553 .WillOnce(Invoke(ReturnErrno(ENOENT))); --- 13 unchanged lines hidden (view full) --- 567 })); 568 569 setup_interruptor(self); 570 ASSERT_EQ(-1, mkdir(FULLDIRPATH0, MODE)); 571 EXPECT_EQ(EINTR, errno); 572} 573 574/* Reads should also be interruptible */ |
566TEST_F(Interrupt, in_progress_read) | 575TEST_F(Intr, in_progress_read) |
567{ 568 const char FULLPATH[] = "mountpoint/some_file.txt"; 569 const char RELPATH[] = "some_file.txt"; 570 const size_t bufsize = 80; 571 char buf[bufsize]; 572 uint64_t ino = 42; 573 int fd; 574 pthread_t self; --- 21 unchanged lines hidden (view full) --- 596 fd = open(FULLPATH, O_RDONLY); 597 ASSERT_LE(0, fd) << strerror(errno); 598 599 setup_interruptor(self); 600 ASSERT_EQ(-1, read(fd, buf, bufsize)); 601 EXPECT_EQ(EINTR, errno); 602} 603 | 576{ 577 const char FULLPATH[] = "mountpoint/some_file.txt"; 578 const char RELPATH[] = "some_file.txt"; 579 const size_t bufsize = 80; 580 char buf[bufsize]; 581 uint64_t ino = 42; 582 int fd; 583 pthread_t self; --- 21 unchanged lines hidden (view full) --- 605 fd = open(FULLPATH, O_RDONLY); 606 ASSERT_LE(0, fd) << strerror(errno); 607 608 setup_interruptor(self); 609 ASSERT_EQ(-1, read(fd, buf, bufsize)); 610 EXPECT_EQ(EINTR, errno); 611} 612 |
613/* 614 * When mounted with -o nointr, fusefs will block signals while waiting for the 615 * server. 616 */ 617TEST_F(Nointr, block) 618{ 619 uint64_t ino = 42; 620 pthread_t self; 621 sem_t sem0; 622 623 ASSERT_EQ(0, sem_init(&sem0, 0, 0)) << strerror(errno); 624 signaled_semaphore = &sem0; 625 self = pthread_self(); 626 627 EXPECT_LOOKUP(FUSE_ROOT_ID, RELDIRPATH0) 628 .WillOnce(Invoke(ReturnErrno(ENOENT))); 629 EXPECT_CALL(*m_mock, process( 630 ResultOf([=](auto in) { 631 return (in.header.opcode == FUSE_MKDIR); 632 }, Eq(true)), 633 _) 634 ).WillOnce(Invoke(ReturnImmediate([&](auto in __unused, auto& out) { 635 /* Let the killer proceed */ 636 sem_post(blocked_semaphore); 637 638 /* Wait until after the signal has been sent */ 639 sem_wait(signaled_semaphore); 640 /* Allow time for the mkdir thread to receive the signal */ 641 nap(); 642 643 /* Finally, complete the original op */ 644 SET_OUT_HEADER_LEN(out, entry); 645 out.body.create.entry.attr.mode = S_IFDIR | MODE; 646 out.body.create.entry.nodeid = ino; 647 }))); 648 EXPECT_CALL(*m_mock, process( 649 ResultOf([&](auto in) { 650 return (in.header.opcode == FUSE_INTERRUPT); 651 }, Eq(true)), 652 _) 653 ).Times(0); 654 655 setup_interruptor(self); 656 ASSERT_EQ(0, mkdir(FULLDIRPATH0, MODE)) << strerror(errno); 657 658 sem_destroy(&sem0); 659} 660 |
|
604/* FUSE_INTERRUPT operations should take priority over other pending ops */ | 661/* FUSE_INTERRUPT operations should take priority over other pending ops */ |
605TEST_F(Interrupt, priority) | 662TEST_F(Intr, priority) |
606{ 607 Sequence seq; 608 uint64_t ino1 = 43; 609 uint64_t mkdir_unique; 610 pthread_t self, th0; 611 sem_t sem0, sem1; 612 613 ASSERT_EQ(0, sem_init(&sem0, 0, 0)) << strerror(errno); --- 69 unchanged lines hidden (view full) --- 683 * original operation to arrive. If not, it should send EAGAIN to the 684 * INTERRUPT operation, and the kernel should requeue the INTERRUPT. 685 * 686 * In this test, we'll pretend that the INTERRUPT arrives too soon, gets 687 * EAGAINed, then the kernel requeues it, and the second time around it 688 * successfully interrupts the original 689 */ 690/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ | 663{ 664 Sequence seq; 665 uint64_t ino1 = 43; 666 uint64_t mkdir_unique; 667 pthread_t self, th0; 668 sem_t sem0, sem1; 669 670 ASSERT_EQ(0, sem_init(&sem0, 0, 0)) << strerror(errno); --- 69 unchanged lines hidden (view full) --- 740 * original operation to arrive. If not, it should send EAGAIN to the 741 * INTERRUPT operation, and the kernel should requeue the INTERRUPT. 742 * 743 * In this test, we'll pretend that the INTERRUPT arrives too soon, gets 744 * EAGAINed, then the kernel requeues it, and the second time around it 745 * successfully interrupts the original 746 */ 747/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ |
691TEST_F(Interrupt, too_soon) | 748TEST_F(Intr, too_soon) |
692{ 693 Sequence seq; 694 pthread_t self; 695 uint64_t mkdir_unique; 696 697 self = pthread_self(); 698 699 EXPECT_LOOKUP(FUSE_ROOT_ID, RELDIRPATH0) --- 34 unchanged lines hidden --- | 749{ 750 Sequence seq; 751 pthread_t self; 752 uint64_t mkdir_unique; 753 754 self = pthread_self(); 755 756 EXPECT_LOOKUP(FUSE_ROOT_ID, RELDIRPATH0) --- 34 unchanged lines hidden --- |