Skip to content

Commit 9d97d6a

Browse files
Brian Fostergregkh
authored andcommitted
xfs: update ag iterator to support wait on new inodes
commit ae2c4ac2dd39b23a87ddb14ceddc3f2872c6aef5 upstream. The AG inode iterator currently skips new inodes as such inodes are inserted into the inode radix tree before they are fully constructed. Certain contexts require the ability to wait on the construction of new inodes, however. The fs-wide dquot release from the quotaoff sequence is an example of this. Update the AG inode iterator to support the ability to wait on inodes flagged with XFS_INEW upon request. Create a new xfs_inode_ag_iterator_flags() interface and support a set of iteration flags to modify the iteration behavior. When the XFS_AGITER_INEW_WAIT flag is set, include XFS_INEW flags in the radix tree inode lookup and wait on them before the callback is executed. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 8e25af0 commit 9d97d6a

2 files changed

Lines changed: 53 additions & 8 deletions

File tree

fs/xfs/xfs_icache.c

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,22 @@ xfs_iget_cache_miss(
366366
return error;
367367
}
368368

369+
static void
370+
xfs_inew_wait(
371+
struct xfs_inode *ip)
372+
{
373+
wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_INEW_BIT);
374+
DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_INEW_BIT);
375+
376+
do {
377+
prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
378+
if (!xfs_iflags_test(ip, XFS_INEW))
379+
break;
380+
schedule();
381+
} while (true);
382+
finish_wait(wq, &wait.wait);
383+
}
384+
369385
/*
370386
* Look up an inode by number in the given file system.
371387
* The inode is looked up in the cache held in each AG.
@@ -470,9 +486,11 @@ xfs_iget(
470486

471487
STATIC int
472488
xfs_inode_ag_walk_grab(
473-
struct xfs_inode *ip)
489+
struct xfs_inode *ip,
490+
int flags)
474491
{
475492
struct inode *inode = VFS_I(ip);
493+
bool newinos = !!(flags & XFS_AGITER_INEW_WAIT);
476494

477495
ASSERT(rcu_read_lock_held());
478496

@@ -490,7 +508,8 @@ xfs_inode_ag_walk_grab(
490508
goto out_unlock_noent;
491509

492510
/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
493-
if (__xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
511+
if ((!newinos && __xfs_iflags_test(ip, XFS_INEW)) ||
512+
__xfs_iflags_test(ip, XFS_IRECLAIMABLE | XFS_IRECLAIM))
494513
goto out_unlock_noent;
495514
spin_unlock(&ip->i_flags_lock);
496515

@@ -518,7 +537,8 @@ xfs_inode_ag_walk(
518537
void *args),
519538
int flags,
520539
void *args,
521-
int tag)
540+
int tag,
541+
int iter_flags)
522542
{
523543
uint32_t first_index;
524544
int last_error = 0;
@@ -560,7 +580,7 @@ xfs_inode_ag_walk(
560580
for (i = 0; i < nr_found; i++) {
561581
struct xfs_inode *ip = batch[i];
562582

563-
if (done || xfs_inode_ag_walk_grab(ip))
583+
if (done || xfs_inode_ag_walk_grab(ip, iter_flags))
564584
batch[i] = NULL;
565585

566586
/*
@@ -588,6 +608,9 @@ xfs_inode_ag_walk(
588608
for (i = 0; i < nr_found; i++) {
589609
if (!batch[i])
590610
continue;
611+
if ((iter_flags & XFS_AGITER_INEW_WAIT) &&
612+
xfs_iflags_test(batch[i], XFS_INEW))
613+
xfs_inew_wait(batch[i]);
591614
error = execute(batch[i], flags, args);
592615
IRELE(batch[i]);
593616
if (error == -EAGAIN) {
@@ -640,12 +663,13 @@ xfs_eofblocks_worker(
640663
}
641664

642665
int
643-
xfs_inode_ag_iterator(
666+
xfs_inode_ag_iterator_flags(
644667
struct xfs_mount *mp,
645668
int (*execute)(struct xfs_inode *ip, int flags,
646669
void *args),
647670
int flags,
648-
void *args)
671+
void *args,
672+
int iter_flags)
649673
{
650674
struct xfs_perag *pag;
651675
int error = 0;
@@ -655,7 +679,8 @@ xfs_inode_ag_iterator(
655679
ag = 0;
656680
while ((pag = xfs_perag_get(mp, ag))) {
657681
ag = pag->pag_agno + 1;
658-
error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1);
682+
error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1,
683+
iter_flags);
659684
xfs_perag_put(pag);
660685
if (error) {
661686
last_error = error;
@@ -666,6 +691,17 @@ xfs_inode_ag_iterator(
666691
return last_error;
667692
}
668693

694+
int
695+
xfs_inode_ag_iterator(
696+
struct xfs_mount *mp,
697+
int (*execute)(struct xfs_inode *ip, int flags,
698+
void *args),
699+
int flags,
700+
void *args)
701+
{
702+
return xfs_inode_ag_iterator_flags(mp, execute, flags, args, 0);
703+
}
704+
669705
int
670706
xfs_inode_ag_iterator_tag(
671707
struct xfs_mount *mp,
@@ -683,7 +719,8 @@ xfs_inode_ag_iterator_tag(
683719
ag = 0;
684720
while ((pag = xfs_perag_get_tag(mp, ag, tag))) {
685721
ag = pag->pag_agno + 1;
686-
error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag);
722+
error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag,
723+
0);
687724
xfs_perag_put(pag);
688725
if (error) {
689726
last_error = error;

fs/xfs/xfs_icache.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ struct xfs_eofblocks {
4848
#define XFS_IGET_UNTRUSTED 0x2
4949
#define XFS_IGET_DONTCACHE 0x4
5050

51+
/*
52+
* flags for AG inode iterator
53+
*/
54+
#define XFS_AGITER_INEW_WAIT 0x1 /* wait on new inodes */
55+
5156
int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino,
5257
uint flags, uint lock_flags, xfs_inode_t **ipp);
5358

@@ -72,6 +77,9 @@ void xfs_eofblocks_worker(struct work_struct *);
7277
int xfs_inode_ag_iterator(struct xfs_mount *mp,
7378
int (*execute)(struct xfs_inode *ip, int flags, void *args),
7479
int flags, void *args);
80+
int xfs_inode_ag_iterator_flags(struct xfs_mount *mp,
81+
int (*execute)(struct xfs_inode *ip, int flags, void *args),
82+
int flags, void *args, int iter_flags);
7583
int xfs_inode_ag_iterator_tag(struct xfs_mount *mp,
7684
int (*execute)(struct xfs_inode *ip, int flags, void *args),
7785
int flags, void *args, int tag);

0 commit comments

Comments
 (0)