aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2017-04-26 11:30:39 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2017-04-28 11:11:08 -0400
commitae2c4ac2dd39b23a87ddb14ceddc3f2872c6aef5 (patch)
treea592c82c0976a79b516884d2f08f7ddbe938c149
parent756baca27fff3ecaeab9dbc7a5ee35a1d7bc0c7f (diff)
xfs: update ag iterator to support wait on new inodes
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>
-rw-r--r--fs/xfs/xfs_icache.c53
-rw-r--r--fs/xfs/xfs_icache.h8
2 files changed, 53 insertions, 8 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 25f4f4595821..f61c84f8e31a 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -262,6 +262,22 @@ xfs_inode_clear_reclaim_tag(
262 xfs_perag_clear_reclaim_tag(pag); 262 xfs_perag_clear_reclaim_tag(pag);
263} 263}
264 264
265static void
266xfs_inew_wait(
267 struct xfs_inode *ip)
268{
269 wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_INEW_BIT);
270 DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_INEW_BIT);
271
272 do {
273 prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
274 if (!xfs_iflags_test(ip, XFS_INEW))
275 break;
276 schedule();
277 } while (true);
278 finish_wait(wq, &wait.wait);
279}
280
265/* 281/*
266 * When we recycle a reclaimable inode, we need to re-initialise the VFS inode 282 * When we recycle a reclaimable inode, we need to re-initialise the VFS inode
267 * part of the structure. This is made more complex by the fact we store 283 * part of the structure. This is made more complex by the fact we store
@@ -626,9 +642,11 @@ out_error_or_again:
626 642
627STATIC int 643STATIC int
628xfs_inode_ag_walk_grab( 644xfs_inode_ag_walk_grab(
629 struct xfs_inode *ip) 645 struct xfs_inode *ip,
646 int flags)
630{ 647{
631 struct inode *inode = VFS_I(ip); 648 struct inode *inode = VFS_I(ip);
649 bool newinos = !!(flags & XFS_AGITER_INEW_WAIT);
632 650
633 ASSERT(rcu_read_lock_held()); 651 ASSERT(rcu_read_lock_held());
634 652
@@ -646,7 +664,8 @@ xfs_inode_ag_walk_grab(
646 goto out_unlock_noent; 664 goto out_unlock_noent;
647 665
648 /* avoid new or reclaimable inodes. Leave for reclaim code to flush */ 666 /* avoid new or reclaimable inodes. Leave for reclaim code to flush */
649 if (__xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM)) 667 if ((!newinos && __xfs_iflags_test(ip, XFS_INEW)) ||
668 __xfs_iflags_test(ip, XFS_IRECLAIMABLE | XFS_IRECLAIM))
650 goto out_unlock_noent; 669 goto out_unlock_noent;
651 spin_unlock(&ip->i_flags_lock); 670 spin_unlock(&ip->i_flags_lock);
652 671
@@ -674,7 +693,8 @@ xfs_inode_ag_walk(
674 void *args), 693 void *args),
675 int flags, 694 int flags,
676 void *args, 695 void *args,
677 int tag) 696 int tag,
697 int iter_flags)
678{ 698{
679 uint32_t first_index; 699 uint32_t first_index;
680 int last_error = 0; 700 int last_error = 0;
@@ -716,7 +736,7 @@ restart:
716 for (i = 0; i < nr_found; i++) { 736 for (i = 0; i < nr_found; i++) {
717 struct xfs_inode *ip = batch[i]; 737 struct xfs_inode *ip = batch[i];
718 738
719 if (done || xfs_inode_ag_walk_grab(ip)) 739 if (done || xfs_inode_ag_walk_grab(ip, iter_flags))
720 batch[i] = NULL; 740 batch[i] = NULL;
721 741
722 /* 742 /*
@@ -744,6 +764,9 @@ restart:
744 for (i = 0; i < nr_found; i++) { 764 for (i = 0; i < nr_found; i++) {
745 if (!batch[i]) 765 if (!batch[i])
746 continue; 766 continue;
767 if ((iter_flags & XFS_AGITER_INEW_WAIT) &&
768 xfs_iflags_test(batch[i], XFS_INEW))
769 xfs_inew_wait(batch[i]);
747 error = execute(batch[i], flags, args); 770 error = execute(batch[i], flags, args);
748 IRELE(batch[i]); 771 IRELE(batch[i]);
749 if (error == -EAGAIN) { 772 if (error == -EAGAIN) {
@@ -823,12 +846,13 @@ xfs_cowblocks_worker(
823} 846}
824 847
825int 848int
826xfs_inode_ag_iterator( 849xfs_inode_ag_iterator_flags(
827 struct xfs_mount *mp, 850 struct xfs_mount *mp,
828 int (*execute)(struct xfs_inode *ip, int flags, 851 int (*execute)(struct xfs_inode *ip, int flags,
829 void *args), 852 void *args),
830 int flags, 853 int flags,
831 void *args) 854 void *args,
855 int iter_flags)
832{ 856{
833 struct xfs_perag *pag; 857 struct xfs_perag *pag;
834 int error = 0; 858 int error = 0;
@@ -838,7 +862,8 @@ xfs_inode_ag_iterator(
838 ag = 0; 862 ag = 0;
839 while ((pag = xfs_perag_get(mp, ag))) { 863 while ((pag = xfs_perag_get(mp, ag))) {
840 ag = pag->pag_agno + 1; 864 ag = pag->pag_agno + 1;
841 error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1); 865 error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1,
866 iter_flags);
842 xfs_perag_put(pag); 867 xfs_perag_put(pag);
843 if (error) { 868 if (error) {
844 last_error = error; 869 last_error = error;
@@ -850,6 +875,17 @@ xfs_inode_ag_iterator(
850} 875}
851 876
852int 877int
878xfs_inode_ag_iterator(
879 struct xfs_mount *mp,
880 int (*execute)(struct xfs_inode *ip, int flags,
881 void *args),
882 int flags,
883 void *args)
884{
885 return xfs_inode_ag_iterator_flags(mp, execute, flags, args, 0);
886}
887
888int
853xfs_inode_ag_iterator_tag( 889xfs_inode_ag_iterator_tag(
854 struct xfs_mount *mp, 890 struct xfs_mount *mp,
855 int (*execute)(struct xfs_inode *ip, int flags, 891 int (*execute)(struct xfs_inode *ip, int flags,
@@ -866,7 +902,8 @@ xfs_inode_ag_iterator_tag(
866 ag = 0; 902 ag = 0;
867 while ((pag = xfs_perag_get_tag(mp, ag, tag))) { 903 while ((pag = xfs_perag_get_tag(mp, ag, tag))) {
868 ag = pag->pag_agno + 1; 904 ag = pag->pag_agno + 1;
869 error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag); 905 error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag,
906 0);
870 xfs_perag_put(pag); 907 xfs_perag_put(pag);
871 if (error) { 908 if (error) {
872 last_error = error; 909 last_error = error;
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index 8a7c849b4dea..9183f77958ef 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -48,6 +48,11 @@ struct xfs_eofblocks {
48#define XFS_IGET_UNTRUSTED 0x2 48#define XFS_IGET_UNTRUSTED 0x2
49#define XFS_IGET_DONTCACHE 0x4 49#define XFS_IGET_DONTCACHE 0x4
50 50
51/*
52 * flags for AG inode iterator
53 */
54#define XFS_AGITER_INEW_WAIT 0x1 /* wait on new inodes */
55
51int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino, 56int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino,
52 uint flags, uint lock_flags, xfs_inode_t **ipp); 57 uint flags, uint lock_flags, xfs_inode_t **ipp);
53 58
@@ -79,6 +84,9 @@ void xfs_cowblocks_worker(struct work_struct *);
79int xfs_inode_ag_iterator(struct xfs_mount *mp, 84int xfs_inode_ag_iterator(struct xfs_mount *mp,
80 int (*execute)(struct xfs_inode *ip, int flags, void *args), 85 int (*execute)(struct xfs_inode *ip, int flags, void *args),
81 int flags, void *args); 86 int flags, void *args);
87int xfs_inode_ag_iterator_flags(struct xfs_mount *mp,
88 int (*execute)(struct xfs_inode *ip, int flags, void *args),
89 int flags, void *args, int iter_flags);
82int xfs_inode_ag_iterator_tag(struct xfs_mount *mp, 90int xfs_inode_ag_iterator_tag(struct xfs_mount *mp,
83 int (*execute)(struct xfs_inode *ip, int flags, void *args), 91 int (*execute)(struct xfs_inode *ip, int flags, void *args),
84 int flags, void *args, int tag); 92 int flags, void *args, int tag);