Skip to content

Commit dc60992

Browse files
Christoph Hellwigcmaiolino
authored andcommitted
xfs: fix finding a last resort AG in xfs_filestream_pick_ag
When the main loop in xfs_filestream_pick_ag fails to find a suitable AG it tries to just pick the online AG. But the loop for that uses args->pag as loop iterator while the later code expects pag to be set. Fix this by reusing the max_pag case for this last resort, and also add a check for impossible case of no AG just to make sure that the uninitialized pag doesn't even escape in theory. Reported-by: [email protected] Signed-off-by: Christoph Hellwig <[email protected]> Tested-by: [email protected] Fixes: f8f1ed1 ("xfs: return a referenced perag from filestreams allocator") Cc: <[email protected]> # v6.3 Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Carlos Maiolino <[email protected]>
1 parent 3ef2268 commit dc60992

File tree

2 files changed

+17
-21
lines changed

2 files changed

+17
-21
lines changed

fs/xfs/xfs_filestream.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ xfs_filestream_pick_ag(
6464
struct xfs_perag *pag;
6565
struct xfs_perag *max_pag = NULL;
6666
xfs_extlen_t minlen = *longest;
67-
xfs_extlen_t free = 0, minfree, maxfree = 0;
67+
xfs_extlen_t minfree, maxfree = 0;
6868
xfs_agnumber_t agno;
6969
bool first_pass = true;
7070
int err;
@@ -107,7 +107,6 @@ xfs_filestream_pick_ag(
107107
!(flags & XFS_PICK_USERDATA) ||
108108
(flags & XFS_PICK_LOWSPACE))) {
109109
/* Break out, retaining the reference on the AG. */
110-
free = pag->pagf_freeblks;
111110
break;
112111
}
113112
}
@@ -150,23 +149,25 @@ xfs_filestream_pick_ag(
150149
* grab.
151150
*/
152151
if (!max_pag) {
153-
for_each_perag_wrap(args->mp, 0, start_agno, args->pag)
152+
for_each_perag_wrap(args->mp, 0, start_agno, pag) {
153+
max_pag = pag;
154154
break;
155-
atomic_inc(&args->pag->pagf_fstrms);
156-
*longest = 0;
157-
} else {
158-
pag = max_pag;
159-
free = maxfree;
160-
atomic_inc(&pag->pagf_fstrms);
155+
}
156+
157+
/* Bail if there are no AGs at all to select from. */
158+
if (!max_pag)
159+
return -ENOSPC;
161160
}
161+
162+
pag = max_pag;
163+
atomic_inc(&pag->pagf_fstrms);
162164
} else if (max_pag) {
163165
xfs_perag_rele(max_pag);
164166
}
165167

166-
trace_xfs_filestream_pick(pag, pino, free);
168+
trace_xfs_filestream_pick(pag, pino);
167169
args->pag = pag;
168170
return 0;
169-
170171
}
171172

172173
static struct xfs_inode *

fs/xfs/xfs_trace.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -691,8 +691,8 @@ DEFINE_FILESTREAM_EVENT(xfs_filestream_lookup);
691691
DEFINE_FILESTREAM_EVENT(xfs_filestream_scan);
692692

693693
TRACE_EVENT(xfs_filestream_pick,
694-
TP_PROTO(struct xfs_perag *pag, xfs_ino_t ino, xfs_extlen_t free),
695-
TP_ARGS(pag, ino, free),
694+
TP_PROTO(struct xfs_perag *pag, xfs_ino_t ino),
695+
TP_ARGS(pag, ino),
696696
TP_STRUCT__entry(
697697
__field(dev_t, dev)
698698
__field(xfs_ino_t, ino)
@@ -703,14 +703,9 @@ TRACE_EVENT(xfs_filestream_pick,
703703
TP_fast_assign(
704704
__entry->dev = pag->pag_mount->m_super->s_dev;
705705
__entry->ino = ino;
706-
if (pag) {
707-
__entry->agno = pag->pag_agno;
708-
__entry->streams = atomic_read(&pag->pagf_fstrms);
709-
} else {
710-
__entry->agno = NULLAGNUMBER;
711-
__entry->streams = 0;
712-
}
713-
__entry->free = free;
706+
__entry->agno = pag->pag_agno;
707+
__entry->streams = atomic_read(&pag->pagf_fstrms);
708+
__entry->free = pag->pagf_freeblks;
714709
),
715710
TP_printk("dev %d:%d ino 0x%llx agno 0x%x streams %d free %d",
716711
MAJOR(__entry->dev), MINOR(__entry->dev),

0 commit comments

Comments
 (0)