Skip to content

Commit 335d318

Browse files
author
Kent Overstreet
committed
bcachefs: bch2_folio_reservation_get_partial() is now better behaved
bch2_folio_reservation_get_partial(), on partial success, will now return a reservation that's aligned to the filesystem blocksize. This is a partial fix for fstests generic/299 - fio verify is badly behaved in the presence of short writes that aren't aligned to its blocksize. Signed-off-by: Kent Overstreet <[email protected]>
1 parent 81e0b6c commit 335d318

File tree

3 files changed

+57
-32
lines changed

3 files changed

+57
-32
lines changed

fs/bcachefs/buckets.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,11 +1160,11 @@ int bch2_trans_mark_dev_sbs(struct bch_fs *c)
11601160
#define SECTORS_CACHE 1024
11611161

11621162
int __bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res,
1163-
u64 sectors, int flags)
1163+
u64 sectors, enum bch_reservation_flags flags)
11641164
{
11651165
struct bch_fs_pcpu *pcpu;
11661166
u64 old, get;
1167-
s64 sectors_available;
1167+
u64 sectors_available;
11681168
int ret;
11691169

11701170
percpu_down_read(&c->mark_lock);
@@ -1202,6 +1202,9 @@ int __bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res,
12021202
percpu_u64_set(&c->pcpu->sectors_available, 0);
12031203
sectors_available = avail_factor(__bch2_fs_usage_read_short(c).free);
12041204

1205+
if (sectors_available && (flags & BCH_DISK_RESERVATION_PARTIAL))
1206+
sectors = min(sectors, sectors_available);
1207+
12051208
if (sectors <= sectors_available ||
12061209
(flags & BCH_DISK_RESERVATION_NOFAIL)) {
12071210
atomic64_set(&c->sectors_available,

fs/bcachefs/buckets.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -344,14 +344,16 @@ static inline void bch2_disk_reservation_put(struct bch_fs *c,
344344
}
345345
}
346346

347-
#define BCH_DISK_RESERVATION_NOFAIL (1 << 0)
347+
enum bch_reservation_flags {
348+
BCH_DISK_RESERVATION_NOFAIL = 1 << 0,
349+
BCH_DISK_RESERVATION_PARTIAL = 1 << 1,
350+
};
348351

349-
int __bch2_disk_reservation_add(struct bch_fs *,
350-
struct disk_reservation *,
351-
u64, int);
352+
int __bch2_disk_reservation_add(struct bch_fs *, struct disk_reservation *,
353+
u64, enum bch_reservation_flags);
352354

353355
static inline int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res,
354-
u64 sectors, int flags)
356+
u64 sectors, enum bch_reservation_flags flags)
355357
{
356358
#ifdef __KERNEL__
357359
u64 old, new;

fs/bcachefs/fs-io-pagecache.c

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -399,14 +399,17 @@ void bch2_folio_reservation_put(struct bch_fs *c,
399399
bch2_quota_reservation_put(c, inode, &res->quota);
400400
}
401401

402-
int bch2_folio_reservation_get(struct bch_fs *c,
402+
static int __bch2_folio_reservation_get(struct bch_fs *c,
403403
struct bch_inode_info *inode,
404404
struct folio *folio,
405405
struct bch2_folio_reservation *res,
406-
size_t offset, size_t len)
406+
size_t offset, size_t len,
407+
bool partial)
407408
{
408409
struct bch_folio *s = bch2_folio_create(folio, 0);
409410
unsigned i, disk_sectors = 0, quota_sectors = 0;
411+
struct disk_reservation disk_res = {};
412+
size_t reserved = len;
410413
int ret;
411414

412415
if (!s)
@@ -422,48 +425,65 @@ int bch2_folio_reservation_get(struct bch_fs *c,
422425
}
423426

424427
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);
426430
if (unlikely(ret))
427431
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+
}
428457
}
429458

430459
if (quota_sectors) {
431460
ret = bch2_quota_reservation_add(c, inode, &res->quota, quota_sectors, true);
432461
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);
437463
return ret;
438464
}
439465
}
440466

441-
return 0;
467+
res->disk.sectors += disk_res.sectors;
468+
return partial ? reserved : 0;
442469
}
443470

444-
ssize_t bch2_folio_reservation_get_partial(struct bch_fs *c,
471+
int bch2_folio_reservation_get(struct bch_fs *c,
445472
struct bch_inode_info *inode,
446473
struct folio *folio,
447474
struct bch2_folio_reservation *res,
448475
size_t offset, size_t len)
449476
{
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+
}
465479

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);
467487
}
468488

469489
static void bch2_clear_folio_bits(struct folio *folio)

0 commit comments

Comments
 (0)