diff --git a/sys/fs/fuse/fuse_ipc.c b/sys/fs/fuse/fuse_ipc.c --- a/sys/fs/fuse/fuse_ipc.c +++ b/sys/fs/fuse/fuse_ipc.c @@ -103,6 +103,7 @@ static void fuse_interrupt_send(struct fuse_ticket *otick, int err); static struct fuse_ticket *fticket_alloc(struct fuse_data *data); static void fticket_refresh(struct fuse_ticket *ftick); +static inline void fticket_reset(struct fuse_ticket *ftick); static void fticket_destroy(struct fuse_ticket *ftick); static int fticket_wait_answer(struct fuse_ticket *ftick); static inline int @@ -318,20 +319,12 @@ FUSE_ASSERT_AW_DONE(ftick); ftick->tk_data = data; - - if (ftick->tk_unique != 0) - fticket_refresh(ftick); - - /* May be truncated to 32 bits */ - ftick->tk_unique = atomic_fetchadd_long(&data->ticketer, 1); - if (ftick->tk_unique == 0) - ftick->tk_unique = atomic_fetchadd_long(&data->ticketer, 1); - ftick->irq_unique = 0; - refcount_init(&ftick->tk_refcount, 1); counter_u64_add(fuse_ticket_count, 1); + fticket_refresh(ftick); + return 0; } @@ -385,26 +378,22 @@ return uma_zfree(ticket_zone, ftick); } -static inline -void +/* Prepare the ticket to be reused and clear its data buffers */ +static inline void fticket_refresh(struct fuse_ticket *ftick) { - FUSE_ASSERT_MS_DONE(ftick); - FUSE_ASSERT_AW_DONE(ftick); + fticket_reset(ftick); fiov_refresh(&ftick->tk_ms_fiov); - - bzero(&ftick->tk_aw_ohead, sizeof(struct fuse_out_header)); - fiov_refresh(&ftick->tk_aw_fiov); - ftick->tk_aw_errno = 0; - ftick->tk_flag = 0; } -/* Prepar the ticket to be reused, but don't clear its data buffers */ +/* Prepare the ticket to be reused, but don't clear its data buffers */ static inline void fticket_reset(struct fuse_ticket *ftick) { + struct fuse_data *data = ftick->tk_data; + FUSE_ASSERT_MS_DONE(ftick); FUSE_ASSERT_AW_DONE(ftick); @@ -412,6 +401,11 @@ ftick->tk_aw_errno = 0; ftick->tk_flag = 0; + + /* May be truncated to 32 bits on LP32 arches */ + ftick->tk_unique = atomic_fetchadd_long(&data->ticketer, 1); + if (ftick->tk_unique == 0) + ftick->tk_unique = atomic_fetchadd_long(&data->ticketer, 1); } static int diff --git a/tests/sys/fs/fusefs/mockfs.hh b/tests/sys/fs/fusefs/mockfs.hh --- a/tests/sys/fs/fusefs/mockfs.hh +++ b/tests/sys/fs/fusefs/mockfs.hh @@ -297,6 +297,9 @@ /* pid of the test process */ pid_t m_pid; + /* The unique value of the header of the last received operation */ + uint64_t m_last_unique; + /* Method the daemon should use for I/O to and from /dev/fuse */ enum poll_method m_pm; diff --git a/tests/sys/fs/fusefs/mockfs.cc b/tests/sys/fs/fusefs/mockfs.cc --- a/tests/sys/fs/fusefs/mockfs.cc +++ b/tests/sys/fs/fusefs/mockfs.cc @@ -408,6 +408,7 @@ m_pm = pm; m_time_gran = time_gran; m_quit = false; + m_last_unique = 0; if (m_pm == KQ) m_kq = kqueue(); else @@ -693,6 +694,14 @@ default: FAIL() << "Unknown opcode " << in.header.opcode; } + /* + * Check that the ticket's unique value is sequential. Technically it + * doesn't need to be sequential, merely unique. But the current + * fusefs driver _does_ make it sequential, and that's easy to check + * for. + */ + if (in.header.unique != ++m_last_unique) + FAIL() << "Non-sequential unique value"; } void MockFS::init(uint32_t flags) {