@@ -399,14 +399,17 @@ void bch2_folio_reservation_put(struct bch_fs *c,
399
399
bch2_quota_reservation_put (c , inode , & res -> quota );
400
400
}
401
401
402
- int bch2_folio_reservation_get (struct bch_fs * c ,
402
+ static int __bch2_folio_reservation_get (struct bch_fs * c ,
403
403
struct bch_inode_info * inode ,
404
404
struct folio * folio ,
405
405
struct bch2_folio_reservation * res ,
406
- size_t offset , size_t len )
406
+ size_t offset , size_t len ,
407
+ bool partial )
407
408
{
408
409
struct bch_folio * s = bch2_folio_create (folio , 0 );
409
410
unsigned i , disk_sectors = 0 , quota_sectors = 0 ;
411
+ struct disk_reservation disk_res = {};
412
+ size_t reserved = len ;
410
413
int ret ;
411
414
412
415
if (!s )
@@ -422,48 +425,65 @@ int bch2_folio_reservation_get(struct bch_fs *c,
422
425
}
423
426
424
427
if (disk_sectors ) {
425
- ret = bch2_disk_reservation_add (c , & res -> disk , disk_sectors , 0 );
428
+ ret = bch2_disk_reservation_add (c , & disk_res , disk_sectors ,
429
+ partial ? BCH_DISK_RESERVATION_PARTIAL : 0 );
426
430
if (unlikely (ret ))
427
431
return ret ;
432
+
433
+ if (unlikely (disk_res .sectors != disk_sectors )) {
434
+ disk_sectors = quota_sectors = 0 ;
435
+
436
+ for (i = round_down (offset , block_bytes (c )) >> 9 ;
437
+ i < round_up (offset + len , block_bytes (c )) >> 9 ;
438
+ i ++ ) {
439
+ disk_sectors += sectors_to_reserve (& s -> s [i ], res -> disk .nr_replicas );
440
+ if (disk_sectors > disk_res .sectors ) {
441
+ /*
442
+ * Make sure to get a reservation that's
443
+ * aligned to the filesystem blocksize:
444
+ */
445
+ unsigned reserved_offset = round_down (i << 9 , block_bytes (c ));
446
+ reserved = clamp (reserved_offset , offset , offset + len ) - offset ;
447
+
448
+ if (!reserved ) {
449
+ bch2_disk_reservation_put (c , & disk_res );
450
+ return - BCH_ERR_ENOSPC_disk_reservation ;
451
+ }
452
+ break ;
453
+ }
454
+ quota_sectors += s -> s [i ].state == SECTOR_unallocated ;
455
+ }
456
+ }
428
457
}
429
458
430
459
if (quota_sectors ) {
431
460
ret = bch2_quota_reservation_add (c , inode , & res -> quota , quota_sectors , true);
432
461
if (unlikely (ret )) {
433
- struct disk_reservation tmp = { .sectors = disk_sectors };
434
- res -> disk .sectors -= disk_sectors ;
435
-
436
- bch2_disk_reservation_put (c , & tmp );
462
+ bch2_disk_reservation_put (c , & disk_res );
437
463
return ret ;
438
464
}
439
465
}
440
466
441
- return 0 ;
467
+ res -> disk .sectors += disk_res .sectors ;
468
+ return partial ? reserved : 0 ;
442
469
}
443
470
444
- ssize_t bch2_folio_reservation_get_partial (struct bch_fs * c ,
471
+ int bch2_folio_reservation_get (struct bch_fs * c ,
445
472
struct bch_inode_info * inode ,
446
473
struct folio * folio ,
447
474
struct bch2_folio_reservation * res ,
448
475
size_t offset , size_t len )
449
476
{
450
- size_t l , reserved = 0 ;
451
- int ret ;
452
-
453
- while ((l = len - reserved )) {
454
- while ((ret = bch2_folio_reservation_get (c , inode , folio , res , offset , l ))) {
455
- if ((offset & (block_bytes (c ) - 1 )) + l <= block_bytes (c ))
456
- return reserved ?: ret ;
457
-
458
- len = reserved + l ;
459
- l /= 2 ;
460
- }
461
-
462
- offset += l ;
463
- reserved += l ;
464
- }
477
+ return __bch2_folio_reservation_get (c , inode , folio , res , offset , len , false);
478
+ }
465
479
466
- return reserved ;
480
+ ssize_t bch2_folio_reservation_get_partial (struct bch_fs * c ,
481
+ struct bch_inode_info * inode ,
482
+ struct folio * folio ,
483
+ struct bch2_folio_reservation * res ,
484
+ size_t offset , size_t len )
485
+ {
486
+ return __bch2_folio_reservation_get (c , inode , folio , res , offset , len , true);
467
487
}
468
488
469
489
static void bch2_clear_folio_bits (struct folio * folio )
0 commit comments