diff options
| -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 | ||
