88#include <linux/list.h>
99#include <linux/types.h>
1010#include <linux/slab.h>
11+ #include <linux/limits.h>
1112#include <linux/interval_tree_generic.h>
1213
1314
@@ -130,16 +131,16 @@ static void fuse_dlm_try_merge(struct fuse_dlm_cache *cache, uint64_t start,
130131 node = rb_first_cached (& cache -> ranges );
131132 while (node ) {
132133 range = rb_entry (node , struct fuse_dlm_range , rb );
133- if (range -> end >= start - 1 )
134+ if (start == 0 || range -> end >= start - 1 )
134135 break ;
135136 node = rb_next (node );
136137 }
137138
138- if (!range || range -> start > end + 1 )
139+ if (!range || ( end != U64_MAX && range -> start > end + 1 ) )
139140 return ;
140141
141142 /* Try to merge ranges in and around the specified region */
142- while (range && range -> start <= end + 1 ) {
143+ while (range && ( end == U64_MAX || range -> start <= end + 1 ) ) {
143144 /* Get next range before we potentially modify the tree */
144145 next = NULL ;
145146 if (rb_next (& range -> rb )) {
@@ -149,9 +150,11 @@ static void fuse_dlm_try_merge(struct fuse_dlm_cache *cache, uint64_t start,
149150
150151 /* Try to merge with next range if adjacent and same mode */
151152 if (next && range -> mode == next -> mode &&
152- range -> end + 1 == next -> start ) {
153- /* Merge ranges */
154- range -> end = next -> end ;
153+ (range -> end == U64_MAX || range -> end + 1 == next -> start )) {
154+ /* Merge ranges - but can't merge if range->end is already U64_MAX */
155+ if (range -> end != U64_MAX ) {
156+ range -> end = next -> end ;
157+ }
155158
156159 /* Remove next from tree */
157160 fuse_page_it_remove (next , & cache -> ranges );
@@ -198,10 +201,25 @@ int fuse_dlm_lock_range(struct fuse_inode *inode, uint64_t start,
198201
199202 /* Convert to lock mode */
200203 lock_mode = (mode == FUSE_PAGE_LOCK_READ ) ? FUSE_PCACHE_LK_READ :
201- FUSE_PCACHE_LK_WRITE ;
204+ FUSE_PCACHE_LK_WRITE ;
202205
203206 down_write (& cache -> lock );
204207
208+ /*
209+ * Fast path: check if the requested range is already fully covered.
210+ * This is an optimization for the common case where we grant
211+ * [0, U64_MAX] locks and avoids overflow arithmetic.
212+ */
213+ range = fuse_page_it_iter_first (& cache -> ranges , start , end );
214+ if (range && range -> start <= start && range -> end >= end ) {
215+ bool same_mode = (range -> mode == lock_mode );
216+ bool stronger_mode = (lock_mode == FUSE_PCACHE_LK_READ &&
217+ range -> mode == FUSE_PCACHE_LK_WRITE );
218+
219+ if (same_mode || stronger_mode )
220+ goto out ;
221+ }
222+
205223 /* Find all ranges that overlap with [start, end] */
206224 range = fuse_page_it_iter_first (& cache -> ranges , start , end );
207225 while (range ) {
@@ -270,6 +288,7 @@ int fuse_dlm_lock_range(struct fuse_inode *inode, uint64_t start,
270288 /* Try to merge adjacent ranges with the same mode */
271289 fuse_dlm_try_merge (cache , start , end );
272290
291+ out :
273292 up_write (& cache -> lock );
274293 return 0 ;
275294
@@ -322,13 +341,25 @@ static int fuse_dlm_punch_hole(struct fuse_dlm_cache *cache, uint64_t start,
322341
323342 /* If the hole is at the beginning of the range */
324343 if (start == range -> start ) {
325- range -> start = end + 1 ;
344+ if (end == U64_MAX ) {
345+ /* Hole goes to end of address space, remove entire range */
346+ fuse_page_it_remove (range , & cache -> ranges );
347+ kfree (range );
348+ } else {
349+ range -> start = end + 1 ;
350+ }
326351 goto out ;
327352 }
328353
329354 /* If the hole is at the end of the range */
330355 if (end == range -> end ) {
331- range -> end = start - 1 ;
356+ if (start == 0 ) {
357+ /* Hole starts at 0, remove entire range */
358+ fuse_page_it_remove (range , & cache -> ranges );
359+ kfree (range );
360+ } else {
361+ range -> end = start - 1 ;
362+ }
332363 goto out ;
333364 }
334365
@@ -399,10 +430,10 @@ int fuse_dlm_unlock_range(struct fuse_inode *inode,
399430 /* After punching a hole, we're done */
400431 break ;
401432 } else if (start > range -> start ) {
402- /* Adjust the end of the range */
433+ /* Adjust the end of the range (start is > 0, so start - 1 is safe) */
403434 range -> end = start - 1 ;
404435 } else if (end < range -> end ) {
405- /* Adjust the start of the range */
436+ /* Adjust the start of the range (end is < U64_MAX, so end + 1 is safe) */
406437 range -> start = end + 1 ;
407438 } else {
408439 /* Complete overlap, remove the range */
@@ -437,6 +468,7 @@ bool fuse_dlm_range_is_locked(struct fuse_inode *inode, uint64_t start,
437468 struct fuse_dlm_range * range ;
438469 int lock_mode = 0 ;
439470 uint64_t current_start = start ;
471+ bool ret = false;
440472
441473 if (!cache || start > end )
442474 return false;
@@ -452,20 +484,34 @@ bool fuse_dlm_range_is_locked(struct fuse_inode *inode, uint64_t start,
452484 /* Find the first range that overlaps with [start, end] */
453485 range = fuse_dlm_find_overlapping (cache , start , end );
454486
455- /* Check if the entire range is covered */
487+ /*
488+ * Fast path: check if a single range covers the entire request.
489+ * This is common when we grant [0, U64_MAX] locks.
490+ */
491+ if (range && range -> start <= start && range -> end >= end ) {
492+ /* Range fully covers [start, end] */
493+ if (!lock_mode || range -> mode == lock_mode ) {
494+ ret = true;
495+ goto out ;
496+ }
497+ /* Wrong lock mode */
498+ goto out ;
499+ }
500+
501+ /* Slow path: check if multiple ranges cover the request */
456502 while (range && current_start <= end ) {
457503 /* If we're checking for a specific mode, verify it matches */
458- if (lock_mode && range -> mode != lock_mode ) {
459- /* Wrong lock mode */
460- up_read (& cache -> lock );
461- return false;
462- }
504+ if (lock_mode && range -> mode != lock_mode )
505+ goto out ;
463506
464507 /* Check if there's a gap before this range */
465- if (current_start < range -> start ) {
466- /* Found a gap */
467- up_read (& cache -> lock );
468- return false;
508+ if (current_start < range -> start )
509+ goto out ;
510+
511+ if (range -> end == U64_MAX ) {
512+ /* Range covers to end of address space */
513+ ret = true;
514+ goto out ;
469515 }
470516
471517 /* Move current_start past this range */
@@ -476,14 +522,11 @@ bool fuse_dlm_range_is_locked(struct fuse_inode *inode, uint64_t start,
476522 }
477523
478524 /* Check if we covered the entire range */
479- if (current_start <= end ) {
480- /* There's a gap at the end */
481- up_read (& cache -> lock );
482- return false;
483- }
525+ ret = (current_start > end );
484526
527+ out :
485528 up_read (& cache -> lock );
486- return true ;
529+ return ret ;
487530}
488531
489532/**
0 commit comments