diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2019-07-03 23:36:28 -0400 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2019-07-04 10:52:23 -0400 |
commit | 13d59a2a61cbbb4cda13a0cba6d4d1fc537f5dd4 (patch) | |
tree | 0870cf2844af43ee8e2c30099c748c1f8ce74e90 | |
parent | fba9760a433634067ec01e7d4cdd581d17b149e0 (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.h | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_ioctl.c | 24 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.c | 6 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.h | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_iwalk.c | 12 | ||||
-rw-r--r-- | fs/xfs/xfs_iwalk.h | 22 | ||||
-rw-r--r-- | fs/xfs/xfs_qm.c | 3 |
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 | |||
586 | xfs_iwalk_threaded( | 590 | xfs_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 | ||
16 | int xfs_iwalk(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t startino, | 16 | int 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); | ||
18 | int xfs_iwalk_threaded(struct xfs_mount *mp, xfs_ino_t startino, | 19 | int 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. */ |
23 | typedef int (*xfs_inobt_walk_fn)(struct xfs_mount *mp, struct xfs_trans *tp, | 29 | typedef 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 | ||
30 | int xfs_inobt_walk(struct xfs_mount *mp, struct xfs_trans *tp, | 36 | int 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 | ||