summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-07-03 23:36:28 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2019-07-04 10:52:23 -0400
commit13d59a2a61cbbb4cda13a0cba6d4d1fc537f5dd4 (patch)
tree0870cf2844af43ee8e2c30099c748c1f8ce74e90
parentfba9760a433634067ec01e7d4cdd581d17b149e0 (diff)
xfs: specify AG in bulk req
Add a new xfs_bulk_ireq flag to constrain the iteration to a single AG. If the passed-in startino value is zero then we start with the first inode in the AG that the user passes in; otherwise, we iterate only within the same AG as the passed-in inode. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Allison Collins <allison.henderson@oracle.com> Reviewed-by: Brian Foster <bfoster@redhat.com>
-rw-r--r--fs/xfs/libxfs/xfs_fs.h10
-rw-r--r--fs/xfs/xfs_ioctl.c24
-rw-r--r--fs/xfs/xfs_itable.c6
-rw-r--r--fs/xfs/xfs_itable.h4
-rw-r--r--fs/xfs/xfs_iwalk.c12
-rw-r--r--fs/xfs/xfs_iwalk.h22
-rw-r--r--fs/xfs/xfs_qm.c3
7 files changed, 69 insertions, 12 deletions
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index aa4918adc6cf..d7b3b712b279 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -462,11 +462,17 @@ struct xfs_bulk_ireq {
462 uint32_t flags; /* I/O: operation flags */ 462 uint32_t flags; /* I/O: operation flags */
463 uint32_t icount; /* I: count of entries in buffer */ 463 uint32_t icount; /* I: count of entries in buffer */
464 uint32_t ocount; /* O: count of entries filled out */ 464 uint32_t ocount; /* O: count of entries filled out */
465 uint32_t reserved32; /* must be zero */ 465 uint32_t agno; /* I: see comment for IREQ_AGNO */
466 uint64_t reserved[5]; /* must be zero */ 466 uint64_t reserved[5]; /* must be zero */
467}; 467};
468 468
469#define XFS_BULK_IREQ_FLAGS_ALL (0) 469/*
470 * Only return results from the specified @agno. If @ino is zero, start
471 * with the first inode of @agno.
472 */
473#define XFS_BULK_IREQ_AGNO (1 << 0)
474
475#define XFS_BULK_IREQ_FLAGS_ALL (XFS_BULK_IREQ_AGNO)
470 476
471/* 477/*
472 * ioctl structures for v5 bulkstat and inumbers requests 478 * ioctl structures for v5 bulkstat and inumbers requests
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index ae7b743df7d0..e1e1d9d6c16d 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -844,7 +844,6 @@ xfs_bulk_ireq_setup(
844{ 844{
845 if (hdr->icount == 0 || 845 if (hdr->icount == 0 ||
846 (hdr->flags & ~XFS_BULK_IREQ_FLAGS_ALL) || 846 (hdr->flags & ~XFS_BULK_IREQ_FLAGS_ALL) ||
847 hdr->reserved32 ||
848 memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved))) 847 memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
849 return -EINVAL; 848 return -EINVAL;
850 849
@@ -852,6 +851,29 @@ xfs_bulk_ireq_setup(
852 breq->ubuffer = ubuffer; 851 breq->ubuffer = ubuffer;
853 breq->icount = hdr->icount; 852 breq->icount = hdr->icount;
854 breq->ocount = 0; 853 breq->ocount = 0;
854 breq->flags = 0;
855
856 /*
857 * The IREQ_AGNO flag means that we only want results from a given AG.
858 * If @hdr->ino is zero, we start iterating in that AG. If @hdr->ino is
859 * beyond the specified AG then we return no results.
860 */
861 if (hdr->flags & XFS_BULK_IREQ_AGNO) {
862 if (hdr->agno >= mp->m_sb.sb_agcount)
863 return -EINVAL;
864
865 if (breq->startino == 0)
866 breq->startino = XFS_AGINO_TO_INO(mp, hdr->agno, 0);
867 else if (XFS_INO_TO_AGNO(mp, breq->startino) < hdr->agno)
868 return -EINVAL;
869
870 breq->flags |= XFS_IBULK_SAME_AG;
871
872 /* Asking for an inode past the end of the AG? We're done! */
873 if (XFS_INO_TO_AGNO(mp, breq->startino) > hdr->agno)
874 return XFS_ITER_ABORT;
875 } else if (hdr->agno)
876 return -EINVAL;
855 877
856 /* Asking for an inode past the end of the FS? We're done! */ 878 /* Asking for an inode past the end of the FS? We're done! */
857 if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount) 879 if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount)
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 687c873fa635..cda8ae94480c 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -247,8 +247,8 @@ xfs_bulkstat(
247 if (!bc.buf) 247 if (!bc.buf)
248 return -ENOMEM; 248 return -ENOMEM;
249 249
250 error = xfs_iwalk(breq->mp, NULL, breq->startino, xfs_bulkstat_iwalk, 250 error = xfs_iwalk(breq->mp, NULL, breq->startino, breq->flags,
251 breq->icount, &bc); 251 xfs_bulkstat_iwalk, breq->icount, &bc);
252 252
253 kmem_free(bc.buf); 253 kmem_free(bc.buf);
254 254
@@ -367,7 +367,7 @@ xfs_inumbers(
367 if (xfs_bulkstat_already_done(breq->mp, breq->startino)) 367 if (xfs_bulkstat_already_done(breq->mp, breq->startino))
368 return 0; 368 return 0;
369 369
370 error = xfs_inobt_walk(breq->mp, NULL, breq->startino, 370 error = xfs_inobt_walk(breq->mp, NULL, breq->startino, breq->flags,
371 xfs_inumbers_walk, breq->icount, &ic); 371 xfs_inumbers_walk, breq->icount, &ic);
372 372
373 /* 373 /*
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index fa9fb9104c7f..e90c1fc5b981 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -12,8 +12,12 @@ struct xfs_ibulk {
12 xfs_ino_t startino; /* start with this inode */ 12 xfs_ino_t startino; /* start with this inode */
13 unsigned int icount; /* number of elements in ubuffer */ 13 unsigned int icount; /* number of elements in ubuffer */
14 unsigned int ocount; /* number of records returned */ 14 unsigned int ocount; /* number of records returned */
15 unsigned int flags; /* see XFS_IBULK_FLAG_* */
15}; 16};
16 17
18/* Only iterate within the same AG as startino */
19#define XFS_IBULK_SAME_AG (XFS_IWALK_SAME_AG)
20
17/* Return value that means we want to abort the walk. */ 21/* Return value that means we want to abort the walk. */
18#define XFS_IBULK_ABORT (XFS_IWALK_ABORT) 22#define XFS_IBULK_ABORT (XFS_IWALK_ABORT)
19 23
diff --git a/fs/xfs/xfs_iwalk.c b/fs/xfs/xfs_iwalk.c
index d3008c20db09..8c7d727149ea 100644
--- a/fs/xfs/xfs_iwalk.c
+++ b/fs/xfs/xfs_iwalk.c
@@ -519,6 +519,7 @@ xfs_iwalk(
519 struct xfs_mount *mp, 519 struct xfs_mount *mp,
520 struct xfs_trans *tp, 520 struct xfs_trans *tp,
521 xfs_ino_t startino, 521 xfs_ino_t startino,
522 unsigned int flags,
522 xfs_iwalk_fn iwalk_fn, 523 xfs_iwalk_fn iwalk_fn,
523 unsigned int inode_records, 524 unsigned int inode_records,
524 void *data) 525 void *data)
@@ -538,6 +539,7 @@ xfs_iwalk(
538 int error; 539 int error;
539 540
540 ASSERT(agno < mp->m_sb.sb_agcount); 541 ASSERT(agno < mp->m_sb.sb_agcount);
542 ASSERT(!(flags & ~XFS_IWALK_FLAGS_ALL));
541 543
542 error = xfs_iwalk_alloc(&iwag); 544 error = xfs_iwalk_alloc(&iwag);
543 if (error) 545 if (error)
@@ -548,6 +550,8 @@ xfs_iwalk(
548 if (error) 550 if (error)
549 break; 551 break;
550 iwag.startino = XFS_AGINO_TO_INO(mp, agno + 1, 0); 552 iwag.startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
553 if (flags & XFS_INOBT_WALK_SAME_AG)
554 break;
551 } 555 }
552 556
553 xfs_iwalk_free(&iwag); 557 xfs_iwalk_free(&iwag);
@@ -586,6 +590,7 @@ int
586xfs_iwalk_threaded( 590xfs_iwalk_threaded(
587 struct xfs_mount *mp, 591 struct xfs_mount *mp,
588 xfs_ino_t startino, 592 xfs_ino_t startino,
593 unsigned int flags,
589 xfs_iwalk_fn iwalk_fn, 594 xfs_iwalk_fn iwalk_fn,
590 unsigned int inode_records, 595 unsigned int inode_records,
591 bool polled, 596 bool polled,
@@ -597,6 +602,7 @@ xfs_iwalk_threaded(
597 int error; 602 int error;
598 603
599 ASSERT(agno < mp->m_sb.sb_agcount); 604 ASSERT(agno < mp->m_sb.sb_agcount);
605 ASSERT(!(flags & ~XFS_IWALK_FLAGS_ALL));
600 606
601 nr_threads = xfs_pwork_guess_datadev_parallelism(mp); 607 nr_threads = xfs_pwork_guess_datadev_parallelism(mp);
602 error = xfs_pwork_init(mp, &pctl, xfs_iwalk_ag_work, "xfs_iwalk", 608 error = xfs_pwork_init(mp, &pctl, xfs_iwalk_ag_work, "xfs_iwalk",
@@ -618,6 +624,8 @@ xfs_iwalk_threaded(
618 iwag->sz_recs = xfs_iwalk_prefetch(inode_records); 624 iwag->sz_recs = xfs_iwalk_prefetch(inode_records);
619 xfs_pwork_queue(&pctl, &iwag->pwork); 625 xfs_pwork_queue(&pctl, &iwag->pwork);
620 startino = XFS_AGINO_TO_INO(mp, agno + 1, 0); 626 startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
627 if (flags & XFS_INOBT_WALK_SAME_AG)
628 break;
621 } 629 }
622 630
623 if (polled) 631 if (polled)
@@ -674,6 +682,7 @@ xfs_inobt_walk(
674 struct xfs_mount *mp, 682 struct xfs_mount *mp,
675 struct xfs_trans *tp, 683 struct xfs_trans *tp,
676 xfs_ino_t startino, 684 xfs_ino_t startino,
685 unsigned int flags,
677 xfs_inobt_walk_fn inobt_walk_fn, 686 xfs_inobt_walk_fn inobt_walk_fn,
678 unsigned int inobt_records, 687 unsigned int inobt_records,
679 void *data) 688 void *data)
@@ -691,6 +700,7 @@ xfs_inobt_walk(
691 int error; 700 int error;
692 701
693 ASSERT(agno < mp->m_sb.sb_agcount); 702 ASSERT(agno < mp->m_sb.sb_agcount);
703 ASSERT(!(flags & ~XFS_INOBT_WALK_FLAGS_ALL));
694 704
695 error = xfs_iwalk_alloc(&iwag); 705 error = xfs_iwalk_alloc(&iwag);
696 if (error) 706 if (error)
@@ -701,6 +711,8 @@ xfs_inobt_walk(
701 if (error) 711 if (error)
702 break; 712 break;
703 iwag.startino = XFS_AGINO_TO_INO(mp, agno + 1, 0); 713 iwag.startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
714 if (flags & XFS_INOBT_WALK_SAME_AG)
715 break;
704 } 716 }
705 717
706 xfs_iwalk_free(&iwag); 718 xfs_iwalk_free(&iwag);
diff --git a/fs/xfs/xfs_iwalk.h b/fs/xfs/xfs_iwalk.h
index 67462861680c..6c960e10ed4d 100644
--- a/fs/xfs/xfs_iwalk.h
+++ b/fs/xfs/xfs_iwalk.h
@@ -14,10 +14,16 @@ typedef int (*xfs_iwalk_fn)(struct xfs_mount *mp, struct xfs_trans *tp,
14#define XFS_IWALK_ABORT (XFS_ITER_ABORT) 14#define XFS_IWALK_ABORT (XFS_ITER_ABORT)
15 15
16int xfs_iwalk(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t startino, 16int xfs_iwalk(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t startino,
17 xfs_iwalk_fn iwalk_fn, unsigned int inode_records, void *data); 17 unsigned int flags, xfs_iwalk_fn iwalk_fn,
18 unsigned int inode_records, void *data);
18int xfs_iwalk_threaded(struct xfs_mount *mp, xfs_ino_t startino, 19int xfs_iwalk_threaded(struct xfs_mount *mp, xfs_ino_t startino,
19 xfs_iwalk_fn iwalk_fn, unsigned int inode_records, bool poll, 20 unsigned int flags, xfs_iwalk_fn iwalk_fn,
20 void *data); 21 unsigned int inode_records, bool poll, void *data);
22
23/* Only iterate inodes within the same AG as @startino. */
24#define XFS_IWALK_SAME_AG (0x1)
25
26#define XFS_IWALK_FLAGS_ALL (XFS_IWALK_SAME_AG)
21 27
22/* Walk all inode btree records in the filesystem starting from @startino. */ 28/* Walk all inode btree records in the filesystem starting from @startino. */
23typedef int (*xfs_inobt_walk_fn)(struct xfs_mount *mp, struct xfs_trans *tp, 29typedef int (*xfs_inobt_walk_fn)(struct xfs_mount *mp, struct xfs_trans *tp,
@@ -28,7 +34,13 @@ typedef int (*xfs_inobt_walk_fn)(struct xfs_mount *mp, struct xfs_trans *tp,
28#define XFS_INOBT_WALK_ABORT (XFS_IWALK_ABORT) 34#define XFS_INOBT_WALK_ABORT (XFS_IWALK_ABORT)
29 35
30int xfs_inobt_walk(struct xfs_mount *mp, struct xfs_trans *tp, 36int xfs_inobt_walk(struct xfs_mount *mp, struct xfs_trans *tp,
31 xfs_ino_t startino, xfs_inobt_walk_fn inobt_walk_fn, 37 xfs_ino_t startino, unsigned int flags,
32 unsigned int inobt_records, void *data); 38 xfs_inobt_walk_fn inobt_walk_fn, unsigned int inobt_records,
39 void *data);
40
41/* Only iterate inobt records within the same AG as @startino. */
42#define XFS_INOBT_WALK_SAME_AG (XFS_IWALK_SAME_AG)
43
44#define XFS_INOBT_WALK_FLAGS_ALL (XFS_INOBT_WALK_SAME_AG)
33 45
34#endif /* __XFS_IWALK_H__ */ 46#endif /* __XFS_IWALK_H__ */
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 2a59c2a43282..5e7a37f0cf84 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1300,7 +1300,8 @@ xfs_qm_quotacheck(
1300 flags |= XFS_PQUOTA_CHKD; 1300 flags |= XFS_PQUOTA_CHKD;
1301 } 1301 }
1302 1302
1303 error = xfs_iwalk_threaded(mp, 0, xfs_qm_dqusage_adjust, 0, true, NULL); 1303 error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
1304 NULL);
1304 if (error) 1305 if (error)
1305 goto error_return; 1306 goto error_return;
1306 1307