@@ -43,8 +43,15 @@ static inline void io_uring_cmd_private_sz_check(size_t cmd_sz)
4343)
4444#endif
4545
46- /* Number of queued fuse requests until a queue is considered full */
47- #define FUSE_URING_QUEUE_THRESHOLD 5
46+ /* Number of queued fuse requests until a queue is considered full
47+ * Basically no entries, as synchronization is with bitmaps and lockless. I.e.
48+ * no accuracy - queues always get a bit more requests that way. Lightly
49+ * loaded queues is wanted to reduced kernel/userspace switches.
50+ */
51+ #define FUSE_URING_QUEUE_THRESHOLD 0
52+
53+ static unsigned int fuse_uring_get_random_qid (struct fuse_ring * ring ,
54+ const struct cpumask * mask );
4855
4956bool fuse_uring_enabled (void )
5057{
@@ -1049,8 +1056,7 @@ static void fuse_uring_ent_avail(struct fuse_ring_ent *ent,
10491056 list_move (& ent -> list , & queue -> ent_avail_queue );
10501057 ent -> state = FRRS_AVAILABLE ;
10511058
1052- if (list_is_singular (& queue -> ent_avail_queue ) &&
1053- queue -> nr_reqs <= FUSE_URING_QUEUE_THRESHOLD ) {
1059+ if (queue -> nr_reqs <= FUSE_URING_QUEUE_THRESHOLD ) {
10541060 cpumask_set_cpu (queue -> qid , ring -> avail_q_mask );
10551061 cpumask_set_cpu (queue -> qid , ring -> per_numa_avail_q_mask [node ]);
10561062 }
@@ -1594,80 +1600,109 @@ static void fuse_uring_send_in_task(struct io_uring_cmd *cmd,
15941600 fuse_uring_send (ent , cmd , err , issue_flags );
15951601}
15961602
1597- static struct fuse_ring_queue * fuse_uring_select_queue ( struct fuse_ring * ring ,
1598- bool background )
1603+ static struct fuse_ring_queue *
1604+ fuse_uring_get_first_queue ( struct fuse_ring * ring , const struct cpumask * mask )
15991605{
1600- unsigned int qid ;
1601- int node , tries = 0 ;
1602- unsigned int nr_queues ;
1603- unsigned int cpu = task_cpu (current );
1604- struct fuse_ring_queue * queue , * primary_queue = NULL ;
1606+ int qid ;
16051607
1606- /*
1607- * Background requests result in better performance on a different
1608- * CPU, unless CPUs are already busy.
1609- */
1610- if (background )
1611- cpu ++ ;
1608+ /* Find the first available CPU in this mask */
1609+ qid = cpumask_first (mask );
16121610
1613- retry :
1614- cpu = cpu % ring -> max_nr_queues ;
1615-
1616- /* numa local registered queue bitmap */
1617- node = cpu_to_node (cpu );
1618- if (WARN_ONCE (node >= ring -> nr_numa_nodes ,
1619- "Node number (%d) exceeds nr nodes (%d)\n" ,
1620- node , ring -> nr_numa_nodes )) {
1621- node = 0 ;
1622- }
1623-
1624- nr_queues = READ_ONCE (ring -> numa_q_map [node ].nr_queues );
1625- if (nr_queues ) {
1626- /* prefer the queue that corresponds to the current cpu */
1627- queue = READ_ONCE (ring -> queues [cpu ]);
1628- if (queue ) {
1629- if (queue -> nr_reqs <= FUSE_URING_Q_THRESHOLD )
1630- return queue ;
1631- primary_queue = queue ;
1632- }
1611+ /* Check if we found a valid CPU */
1612+ if (qid >= ring -> max_nr_queues )
1613+ return NULL ; /* No available queues */
1614+
1615+ /* This is the global mask, cpu is already the global qid */
1616+ return ring -> queues [qid ];
1617+ }
16331618
1634- qid = ring -> numa_q_map [node ].cpu_to_qid [cpu ];
1635- if (WARN_ON_ONCE (qid >= ring -> max_nr_queues ))
1636- return NULL ;
1637- if (qid != cpu ) {
1638- queue = READ_ONCE (ring -> queues [qid ]);
1619+ /*
1620+ * Return a random queue from the registered queues mask
1621+ *
1622+ * Uses a deterministic but well-distributed algorithm to select
1623+ * a random queue from the provided CPU mask.
1624+ */
1625+ static unsigned int fuse_uring_get_random_qid (struct fuse_ring * ring ,
1626+ const struct cpumask * mask )
1627+ {
1628+ unsigned int nr_bits = cpumask_weight (mask );
1629+ unsigned int nth , cpu ;
16391630
1640- /* Might happen on teardown */
1641- if (unlikely (!queue ))
1642- return NULL ;
1631+ if (nr_bits == 0 )
1632+ return UINT_MAX ;
16431633
1644- if ( queue -> nr_reqs <= FUSE_URING_Q_THRESHOLD )
1645- return queue ;
1646- }
1634+ /* Fast path for single CPU */
1635+ if ( nr_bits == 1 )
1636+ return cpumask_first ( mask );
16471637
1648- /* Retries help for load balancing */
1649- if (tries < FUSE_URING_Q_TRIES && tries + 1 < nr_queues ) {
1650- if (!primary_queue )
1651- primary_queue = queue ;
1638+ /*
1639+ * Use current jiffies and task PID to create a pseudo-random
1640+ * but well-distributed selection that varies across calls
1641+ */
1642+ nth = (get_random_u32 () ^ (jiffies & 0xFFFF ) ^
1643+ (current -> pid & 0xFFFF )) %
1644+ nr_bits ;
16521645
1653- /* Increase cpu, assuming it will map to a different qid*/
1654- cpu ++ ;
1655- tries ++ ;
1656- goto retry ;
1657- }
1646+ /* Find the CPU at that position */
1647+ for_each_cpu (cpu , mask ) {
1648+ if (nth -- == 0 )
1649+ return cpu ;
16581650 }
16591651
1660- /* Retries exceeded, take the primary target queue */
1661- if (primary_queue )
1662- return primary_queue ;
1652+ return UINT_MAX ;
1653+ }
16631654
1664- /* global registered queue bitmap */
1665- qid = ring -> q_map .cpu_to_qid [cpu ];
1666- if (WARN_ON_ONCE (qid >= ring -> max_nr_queues )) {
1667- /* Might happen on teardown */
1668- return NULL ;
1669- }
1670- return READ_ONCE (ring -> queues [qid ]);
1655+ /*
1656+ * Get the best queue for the current CPU
1657+ */
1658+ static struct fuse_ring_queue * fuse_uring_get_queue (struct fuse_ring * ring )
1659+ {
1660+ unsigned int qid ;
1661+ struct fuse_ring_queue * queue , * local_queue = NULL ;
1662+ int local_node ;
1663+ struct cpumask * mask ;
1664+ struct fuse_conn * fc = ring -> fc ;
1665+
1666+ qid = task_cpu (current );
1667+ local_node = cpu_to_node (qid );
1668+ if (WARN_ON_ONCE (local_node >= ring -> nr_numa_nodes || local_node < 0 ))
1669+ local_node = 0 ;
1670+
1671+ /* First check if current CPU's queue is available */
1672+ if (qid < ring -> max_nr_queues ) {
1673+ local_queue = queue = ring -> queues [qid ];
1674+ if (queue && queue -> nr_reqs <= FUSE_URING_QUEUE_THRESHOLD )
1675+ return queue ;
1676+ }
1677+
1678+ /* Second check if there are any available queues on the local node */
1679+ mask = ring -> per_numa_avail_q_mask [local_node ];
1680+ queue = fuse_uring_get_first_queue (ring , mask );
1681+ if (queue )
1682+ return queue ;
1683+
1684+ /* Third check if there are any available queues on any node */
1685+ queue = fuse_uring_get_first_queue (ring , ring -> avail_q_mask );
1686+ if (queue )
1687+ return queue ;
1688+
1689+ /* No free queue, use the local queue if it exists */
1690+ if (local_queue )
1691+ return local_queue ;
1692+
1693+ /* Try to use a random queue from the local NUMA node, if there is one */
1694+ mask = ring -> numa_registered_q_mask [local_node ];
1695+ qid = fuse_uring_get_random_qid (ring , mask );
1696+ if (qid < ring -> max_nr_queues )
1697+ return ring -> queues [qid ];
1698+
1699+ /* Finally, use a random queue among all queues that are registered */
1700+ qid = fuse_uring_get_random_qid (ring , ring -> registered_q_mask );
1701+ if (qid < ring -> max_nr_queues )
1702+ return ring -> queues [qid ];
1703+
1704+ WARN_ON_ONCE (fc -> connected );
1705+ return NULL ;
16711706}
16721707
16731708static void fuse_uring_dispatch_ent (struct fuse_ring_ent * ent , bool bg )
@@ -1707,7 +1742,7 @@ void fuse_uring_queue_fuse_req(struct fuse_iqueue *fiq, struct fuse_req *req)
17071742 int err ;
17081743
17091744 err = - EINVAL ;
1710- queue = fuse_uring_select_queue (ring , false );
1745+ queue = fuse_uring_get_queue (ring );
17111746 if (!queue )
17121747 goto err ;
17131748
@@ -1722,6 +1757,19 @@ void fuse_uring_queue_fuse_req(struct fuse_iqueue *fiq, struct fuse_req *req)
17221757 struct fuse_ring_ent , list );
17231758 queue -> nr_reqs ++ ;
17241759
1760+ /*
1761+ * Update queue availability based on number of requests
1762+ * A queue is considered busy if it has more than
1763+ * FUSE_URING_QUEUE_THRESHOLD requests
1764+ */
1765+ if (queue -> nr_reqs == FUSE_URING_QUEUE_THRESHOLD + 1 ) {
1766+ /* Queue just became busy */
1767+ cpumask_clear_cpu (queue -> qid , ring -> avail_q_mask );
1768+ cpumask_clear_cpu (
1769+ queue -> qid ,
1770+ ring -> per_numa_avail_q_mask [queue -> numa_node ]);
1771+ }
1772+
17251773 if (ent )
17261774 fuse_uring_add_req_to_ring_ent (ent , req );
17271775 else
@@ -1749,7 +1797,7 @@ bool fuse_uring_queue_bq_req(struct fuse_req *req)
17491797 struct fuse_ring_queue * queue ;
17501798 struct fuse_ring_ent * ent = NULL ;
17511799
1752- queue = fuse_uring_select_queue (ring , true );
1800+ queue = fuse_uring_get_queue (ring );
17531801 if (!queue )
17541802 return false;
17551803
@@ -1795,12 +1843,25 @@ bool fuse_uring_queue_bq_req(struct fuse_req *req)
17951843bool fuse_uring_remove_pending_req (struct fuse_req * req )
17961844{
17971845 struct fuse_ring_queue * queue = req -> ring_queue ;
1846+ struct fuse_ring * ring = queue -> ring ;
1847+ int node = queue -> numa_node ;
17981848 bool removed = fuse_remove_pending_req (req , & queue -> lock );
17991849
18001850 if (removed ) {
18011851 /* Update counters after successful removal */
18021852 spin_lock (& queue -> lock );
18031853 queue -> nr_reqs -- ;
1854+
1855+ /*
1856+ * Update queue availability based on number of requests
1857+ * A queue is considered available if it has FUSE_URING_QUEUE_THRESHOLD or fewer requests
1858+ */
1859+ if (queue -> nr_reqs == FUSE_URING_QUEUE_THRESHOLD ) {
1860+ /* Queue just became available */
1861+ cpumask_set_cpu (queue -> qid , ring -> avail_q_mask );
1862+ cpumask_set_cpu (queue -> qid ,
1863+ ring -> per_numa_avail_q_mask [node ]);
1864+ }
18041865 spin_unlock (& queue -> lock );
18051866 }
18061867
0 commit comments