Skip to content

Commit af12070

Browse files
committed
Merge tag 'xfs-5.13-merge-5' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull more xfs updates from Darrick Wong: "Except for the timestamp struct renaming patches, everything else in here are bug fixes: - Rename the log timestamp struct. - Remove broken transaction counter debugging that wasn't working correctly on very old filesystems. - Various fixes to make pre-lazysbcount filesystems work properly again. - Fix a free space accounting problem where we neglected to consider free space btree blocks that track metadata reservation space when deciding whether or not to allow caller to reserve space for a metadata update. - Fix incorrect pagecache clearing behavior during FUNSHARE ops. - Don't allow log writes if the data device is readonly" * tag 'xfs-5.13-merge-5' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: don't allow log writes if the data device is readonly xfs: fix xfs_reflink_unshare usage of filemap_write_and_wait_range xfs: set aside allocation btree blocks from block reservation xfs: introduce in-core global counter of allocbt blocks xfs: unconditionally read all AGFs on mounts with perag reservation xfs: count free space btree blocks when scrubbing pre-lazysbcount fses xfs: update superblock counters correctly for !lazysbcount xfs: don't check agf_btreeblks on pre-lazysbcount filesystems xfs: remove obsolete AGF counter debugging xfs: rename struct xfs_legacy_ictimestamp xfs: rename xfs_ictimestamp_t
2 parents aef511f + 8e9800f commit af12070

18 files changed

+143
-68
lines changed

fs/xfs/libxfs/xfs_ag_resv.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ xfs_ag_resv_init(
253253
xfs_agnumber_t agno = pag->pag_agno;
254254
xfs_extlen_t ask;
255255
xfs_extlen_t used;
256-
int error = 0;
256+
int error = 0, error2;
257+
bool has_resv = false;
257258

258259
/* Create the metadata reservation. */
259260
if (pag->pag_meta_resv.ar_asked == 0) {
@@ -291,6 +292,8 @@ xfs_ag_resv_init(
291292
if (error)
292293
goto out;
293294
}
295+
if (ask)
296+
has_resv = true;
294297
}
295298

296299
/* Create the RMAPBT metadata reservation */
@@ -304,19 +307,28 @@ xfs_ag_resv_init(
304307
error = __xfs_ag_resv_init(pag, XFS_AG_RESV_RMAPBT, ask, used);
305308
if (error)
306309
goto out;
310+
if (ask)
311+
has_resv = true;
307312
}
308313

309-
#ifdef DEBUG
310-
/* need to read in the AGF for the ASSERT below to work */
311-
error = xfs_alloc_pagf_init(pag->pag_mount, tp, pag->pag_agno, 0);
312-
if (error)
313-
return error;
314-
315-
ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved +
316-
xfs_perag_resv(pag, XFS_AG_RESV_RMAPBT)->ar_reserved <=
317-
pag->pagf_freeblks + pag->pagf_flcount);
318-
#endif
319314
out:
315+
/*
316+
* Initialize the pagf if we have at least one active reservation on the
317+
* AG. This may have occurred already via reservation calculation, but
318+
* fall back to an explicit init to ensure the in-core allocbt usage
319+
* counters are initialized as soon as possible. This is important
320+
* because filesystems with large perag reservations are susceptible to
321+
* free space reservation problems that the allocbt counter is used to
322+
* address.
323+
*/
324+
if (has_resv) {
325+
error2 = xfs_alloc_pagf_init(mp, tp, pag->pag_agno, 0);
326+
if (error2)
327+
return error2;
328+
ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved +
329+
xfs_perag_resv(pag, XFS_AG_RESV_RMAPBT)->ar_reserved <=
330+
pag->pagf_freeblks + pag->pagf_flcount);
331+
}
320332
return error;
321333
}
322334

fs/xfs/libxfs/xfs_alloc.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,6 @@ xfs_alloc_update_counters(
718718
agbp->b_pag->pagf_freeblks += len;
719719
be32_add_cpu(&agf->agf_freeblks, len);
720720

721-
xfs_trans_agblocks_delta(tp, len);
722721
if (unlikely(be32_to_cpu(agf->agf_freeblks) >
723722
be32_to_cpu(agf->agf_length))) {
724723
xfs_buf_mark_corrupt(agbp);
@@ -2739,7 +2738,6 @@ xfs_alloc_get_freelist(
27392738
pag = agbp->b_pag;
27402739
ASSERT(!pag->pagf_agflreset);
27412740
be32_add_cpu(&agf->agf_flcount, -1);
2742-
xfs_trans_agflist_delta(tp, -1);
27432741
pag->pagf_flcount--;
27442742

27452743
logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
@@ -2846,7 +2844,6 @@ xfs_alloc_put_freelist(
28462844
pag = agbp->b_pag;
28472845
ASSERT(!pag->pagf_agflreset);
28482846
be32_add_cpu(&agf->agf_flcount, 1);
2849-
xfs_trans_agflist_delta(tp, 1);
28502847
pag->pagf_flcount++;
28512848

28522849
logflags = XFS_AGF_FLLAST | XFS_AGF_FLCOUNT;
@@ -3036,6 +3033,7 @@ xfs_alloc_read_agf(
30363033
struct xfs_agf *agf; /* ag freelist header */
30373034
struct xfs_perag *pag; /* per allocation group data */
30383035
int error;
3036+
int allocbt_blks;
30393037

30403038
trace_xfs_alloc_read_agf(mp, agno);
30413039

@@ -3066,6 +3064,19 @@ xfs_alloc_read_agf(
30663064
pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);
30673065
pag->pagf_init = 1;
30683066
pag->pagf_agflreset = xfs_agfl_needs_reset(mp, agf);
3067+
3068+
/*
3069+
* Update the in-core allocbt counter. Filter out the rmapbt
3070+
* subset of the btreeblks counter because the rmapbt is managed
3071+
* by perag reservation. Subtract one for the rmapbt root block
3072+
* because the rmap counter includes it while the btreeblks
3073+
* counter only tracks non-root blocks.
3074+
*/
3075+
allocbt_blks = pag->pagf_btreeblks;
3076+
if (xfs_sb_version_hasrmapbt(&mp->m_sb))
3077+
allocbt_blks -= be32_to_cpu(agf->agf_rmap_blocks) - 1;
3078+
if (allocbt_blks > 0)
3079+
atomic64_add(allocbt_blks, &mp->m_allocbt_blks);
30693080
}
30703081
#ifdef DEBUG
30713082
else if (!XFS_FORCED_SHUTDOWN(mp)) {

fs/xfs/libxfs/xfs_alloc_btree.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ xfs_allocbt_alloc_block(
7171
return 0;
7272
}
7373

74+
atomic64_inc(&cur->bc_mp->m_allocbt_blks);
7475
xfs_extent_busy_reuse(cur->bc_mp, cur->bc_ag.agno, bno, 1, false);
7576

76-
xfs_trans_agbtree_delta(cur->bc_tp, 1);
7777
new->s = cpu_to_be32(bno);
7878

7979
*stat = 1;
@@ -95,9 +95,9 @@ xfs_allocbt_free_block(
9595
if (error)
9696
return error;
9797

98+
atomic64_dec(&cur->bc_mp->m_allocbt_blks);
9899
xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,
99100
XFS_EXTENT_BUSY_SKIP_DISCARD);
100-
xfs_trans_agbtree_delta(cur->bc_tp, -1);
101101
return 0;
102102
}
103103

fs/xfs/libxfs/xfs_log_format.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -368,10 +368,10 @@ static inline int xfs_ilog_fdata(int w)
368368
* directly mirrors the xfs_dinode structure as it must contain all the same
369369
* information.
370370
*/
371-
typedef uint64_t xfs_ictimestamp_t;
371+
typedef uint64_t xfs_log_timestamp_t;
372372

373373
/* Legacy timestamp encoding format. */
374-
struct xfs_legacy_ictimestamp {
374+
struct xfs_log_legacy_timestamp {
375375
int32_t t_sec; /* timestamp seconds */
376376
int32_t t_nsec; /* timestamp nanoseconds */
377377
};
@@ -393,9 +393,9 @@ struct xfs_log_dinode {
393393
uint16_t di_projid_hi; /* higher part of owner's project id */
394394
uint8_t di_pad[6]; /* unused, zeroed space */
395395
uint16_t di_flushiter; /* incremented on flush */
396-
xfs_ictimestamp_t di_atime; /* time last accessed */
397-
xfs_ictimestamp_t di_mtime; /* time last modified */
398-
xfs_ictimestamp_t di_ctime; /* time created/inode modified */
396+
xfs_log_timestamp_t di_atime; /* time last accessed */
397+
xfs_log_timestamp_t di_mtime; /* time last modified */
398+
xfs_log_timestamp_t di_ctime; /* time created/inode modified */
399399
xfs_fsize_t di_size; /* number of bytes in file */
400400
xfs_rfsblock_t di_nblocks; /* # of direct & btree blocks used */
401401
xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
@@ -420,7 +420,7 @@ struct xfs_log_dinode {
420420
uint8_t di_pad2[12]; /* more padding for future expansion */
421421

422422
/* fields only written to during inode creation */
423-
xfs_ictimestamp_t di_crtime; /* time created */
423+
xfs_log_timestamp_t di_crtime; /* time created */
424424
xfs_ino_t di_ino; /* inode number */
425425
uuid_t di_uuid; /* UUID of the filesystem */
426426

fs/xfs/libxfs/xfs_rmap_btree.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ xfs_rmapbt_alloc_block(
103103
xfs_extent_busy_reuse(cur->bc_mp, cur->bc_ag.agno, bno, 1,
104104
false);
105105

106-
xfs_trans_agbtree_delta(cur->bc_tp, 1);
107106
new->s = cpu_to_be32(bno);
108107
be32_add_cpu(&agf->agf_rmap_blocks, 1);
109108
xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_RMAP_BLOCKS);
@@ -136,7 +135,6 @@ xfs_rmapbt_free_block(
136135

137136
xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,
138137
XFS_EXTENT_BUSY_SKIP_DISCARD);
139-
xfs_trans_agbtree_delta(cur->bc_tp, -1);
140138

141139
pag = cur->bc_ag.agbp->b_pag;
142140
xfs_ag_resv_free_extent(pag, XFS_AG_RESV_RMAPBT, NULL, 1);

fs/xfs/libxfs/xfs_sb.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -926,9 +926,19 @@ xfs_log_sb(
926926
struct xfs_mount *mp = tp->t_mountp;
927927
struct xfs_buf *bp = xfs_trans_getsb(tp);
928928

929-
mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
930-
mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree);
931-
mp->m_sb.sb_fdblocks = percpu_counter_sum(&mp->m_fdblocks);
929+
/*
930+
* Lazy sb counters don't update the in-core superblock so do that now.
931+
* If this is at unmount, the counters will be exactly correct, but at
932+
* any other time they will only be ballpark correct because of
933+
* reservations that have been taken out percpu counters. If we have an
934+
* unclean shutdown, this will be corrected by log recovery rebuilding
935+
* the counters from the AGF block counts.
936+
*/
937+
if (xfs_sb_version_haslazysbcount(&mp->m_sb)) {
938+
mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
939+
mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree);
940+
mp->m_sb.sb_fdblocks = percpu_counter_sum(&mp->m_fdblocks);
941+
}
932942

933943
xfs_sb_to_disk(bp->b_addr, &mp->m_sb);
934944
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);

fs/xfs/scrub/agheader.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,10 @@ xchk_agf_xref_btreeblks(
416416
xfs_agblock_t btreeblks;
417417
int error;
418418

419+
/* agf_btreeblks didn't exist before lazysbcount */
420+
if (!xfs_sb_version_haslazysbcount(&sc->mp->m_sb))
421+
return;
422+
419423
/* Check agf_rmap_blocks; set up for agf_btreeblks check */
420424
if (sc->sa.rmap_cur) {
421425
error = xfs_btree_count_blocks(sc->sa.rmap_cur, &blocks);
@@ -581,7 +585,8 @@ xchk_agf(
581585
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
582586
if (pag->pagf_flcount != be32_to_cpu(agf->agf_flcount))
583587
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
584-
if (pag->pagf_btreeblks != be32_to_cpu(agf->agf_btreeblks))
588+
if (xfs_sb_version_haslazysbcount(&sc->mp->m_sb) &&
589+
pag->pagf_btreeblks != be32_to_cpu(agf->agf_btreeblks))
585590
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
586591
xfs_perag_put(pag);
587592

fs/xfs/scrub/fscounters.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "xfs_alloc.h"
1414
#include "xfs_ialloc.h"
1515
#include "xfs_health.h"
16+
#include "xfs_btree.h"
1617
#include "scrub/scrub.h"
1718
#include "scrub/common.h"
1819
#include "scrub/trace.h"
@@ -143,6 +144,35 @@ xchk_setup_fscounters(
143144
return xchk_trans_alloc(sc, 0);
144145
}
145146

147+
/* Count free space btree blocks manually for pre-lazysbcount filesystems. */
148+
static int
149+
xchk_fscount_btreeblks(
150+
struct xfs_scrub *sc,
151+
struct xchk_fscounters *fsc,
152+
xfs_agnumber_t agno)
153+
{
154+
xfs_extlen_t blocks;
155+
int error;
156+
157+
error = xchk_ag_init(sc, agno, &sc->sa);
158+
if (error)
159+
return error;
160+
161+
error = xfs_btree_count_blocks(sc->sa.bno_cur, &blocks);
162+
if (error)
163+
goto out_free;
164+
fsc->fdblocks += blocks - 1;
165+
166+
error = xfs_btree_count_blocks(sc->sa.cnt_cur, &blocks);
167+
if (error)
168+
goto out_free;
169+
fsc->fdblocks += blocks - 1;
170+
171+
out_free:
172+
xchk_ag_free(sc, &sc->sa);
173+
return error;
174+
}
175+
146176
/*
147177
* Calculate what the global in-core counters ought to be from the incore
148178
* per-AG structure. Callers can compare this to the actual in-core counters
@@ -182,7 +212,15 @@ xchk_fscount_aggregate_agcounts(
182212
/* Add up the free/freelist/bnobt/cntbt blocks */
183213
fsc->fdblocks += pag->pagf_freeblks;
184214
fsc->fdblocks += pag->pagf_flcount;
185-
fsc->fdblocks += pag->pagf_btreeblks;
215+
if (xfs_sb_version_haslazysbcount(&sc->mp->m_sb)) {
216+
fsc->fdblocks += pag->pagf_btreeblks;
217+
} else {
218+
error = xchk_fscount_btreeblks(sc, fsc, agno);
219+
if (error) {
220+
xfs_perag_put(pag);
221+
break;
222+
}
223+
}
186224

187225
/*
188226
* Per-AG reservations are taken out of the incore counters,

fs/xfs/xfs_fsops.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ xfs_resizefs_init_new_ags(
6969
if (error)
7070
return error;
7171

72-
xfs_trans_agblocks_delta(tp, id->nfree);
73-
7472
if (delta) {
7573
*lastag_extended = true;
7674
error = xfs_ag_extend_space(mp, tp, id, delta);

fs/xfs/xfs_inode_item.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,18 +299,18 @@ xfs_inode_item_format_attr_fork(
299299
* Convert an incore timestamp to a log timestamp. Note that the log format
300300
* specifies host endian format!
301301
*/
302-
static inline xfs_ictimestamp_t
302+
static inline xfs_log_timestamp_t
303303
xfs_inode_to_log_dinode_ts(
304304
struct xfs_inode *ip,
305305
const struct timespec64 tv)
306306
{
307-
struct xfs_legacy_ictimestamp *lits;
308-
xfs_ictimestamp_t its;
307+
struct xfs_log_legacy_timestamp *lits;
308+
xfs_log_timestamp_t its;
309309

310310
if (xfs_inode_has_bigtime(ip))
311311
return xfs_inode_encode_bigtime(tv);
312312

313-
lits = (struct xfs_legacy_ictimestamp *)&its;
313+
lits = (struct xfs_log_legacy_timestamp *)&its;
314314
lits->t_sec = tv.tv_sec;
315315
lits->t_nsec = tv.tv_nsec;
316316

0 commit comments

Comments
 (0)