aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2017-06-29 15:28:36 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2017-07-02 00:09:33 -0400
commitbda250dbaf39f67f8910e183853e4e6a9e5ce899 (patch)
treed5fbd300007d1e7bcc88eb93c14c45d89206e03a
parentd04c241c669209667dd8f44335591246e601139a (diff)
xfs: rewrite xfs_dq_get_next_id using xfs_iext_lookup_extent
This goes straight to a single lookup in the extent list and avoids a roundtrip through two layers that don't add any value for the simple quoata file that just has data or holes and no page cache, delayed allocation, unwritten extent or COW fork (which btw, doesn't seem to be handled by the existing SEEK HOLE/DATA code). Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Eric Sandeen <sandeen@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_dquot.c66
1 files changed, 22 insertions, 44 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 79668142afc1..8848b397e7a8 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -701,21 +701,18 @@ error0:
701 */ 701 */
702static int 702static int
703xfs_dq_get_next_id( 703xfs_dq_get_next_id(
704 xfs_mount_t *mp, 704 struct xfs_mount *mp,
705 uint type, 705 uint type,
706 xfs_dqid_t *id, 706 xfs_dqid_t *id)
707 loff_t eof)
708{ 707{
709 struct xfs_inode *quotip; 708 struct xfs_inode *quotip = xfs_quota_inode(mp, type);
709 xfs_dqid_t next_id = *id + 1; /* simple advance */
710 uint lock_flags;
711 struct xfs_bmbt_irec got;
712 xfs_extnum_t idx;
710 xfs_fsblock_t start; 713 xfs_fsblock_t start;
711 loff_t offset;
712 uint lock;
713 xfs_dqid_t next_id;
714 int error = 0; 714 int error = 0;
715 715
716 /* Simple advance */
717 next_id = *id + 1;
718
719 /* If we'd wrap past the max ID, stop */ 716 /* If we'd wrap past the max ID, stop */
720 if (next_id < *id) 717 if (next_id < *id)
721 return -ENOENT; 718 return -ENOENT;
@@ -729,23 +726,20 @@ xfs_dq_get_next_id(
729 /* Nope, next_id is now past the current chunk, so find the next one */ 726 /* Nope, next_id is now past the current chunk, so find the next one */
730 start = (xfs_fsblock_t)next_id / mp->m_quotainfo->qi_dqperchunk; 727 start = (xfs_fsblock_t)next_id / mp->m_quotainfo->qi_dqperchunk;
731 728
732 quotip = xfs_quota_inode(mp, type); 729 lock_flags = xfs_ilock_data_map_shared(quotip);
733 lock = xfs_ilock_data_map_shared(quotip); 730 if (!(quotip->i_df.if_flags & XFS_IFEXTENTS)) {
734 731 error = xfs_iread_extents(NULL, quotip, XFS_DATA_FORK);
735 offset = __xfs_seek_hole_data(VFS_I(quotip), XFS_FSB_TO_B(mp, start), 732 if (error)
736 eof, SEEK_DATA); 733 return error;
737 if (offset < 0) 734 }
738 error = offset;
739
740 xfs_iunlock(quotip, lock);
741 735
742 /* -ENXIO is essentially "no more data" */ 736 if (xfs_iext_lookup_extent(quotip, &quotip->i_df, start, &idx, &got))
743 if (error) 737 *id = got.br_startoff * mp->m_quotainfo->qi_dqperchunk;
744 return (error == -ENXIO ? -ENOENT: error); 738 else
739 error = -ENOENT;
740 xfs_iunlock(quotip, lock_flags);
745 741
746 /* Convert next data offset back to a quota id */ 742 return error;
747 *id = XFS_B_TO_FSB(mp, offset) * mp->m_quotainfo->qi_dqperchunk;
748 return 0;
749} 743}
750 744
751/* 745/*
@@ -768,7 +762,6 @@ xfs_qm_dqget(
768 struct xfs_quotainfo *qi = mp->m_quotainfo; 762 struct xfs_quotainfo *qi = mp->m_quotainfo;
769 struct radix_tree_root *tree = xfs_dquot_tree(qi, type); 763 struct radix_tree_root *tree = xfs_dquot_tree(qi, type);
770 struct xfs_dquot *dqp; 764 struct xfs_dquot *dqp;
771 loff_t eof = 0;
772 int error; 765 int error;
773 766
774 ASSERT(XFS_IS_QUOTA_RUNNING(mp)); 767 ASSERT(XFS_IS_QUOTA_RUNNING(mp));
@@ -796,21 +789,6 @@ xfs_qm_dqget(
796 } 789 }
797#endif 790#endif
798 791
799 /* Get the end of the quota file if we need it */
800 if (flags & XFS_QMOPT_DQNEXT) {
801 struct xfs_inode *quotip;
802 xfs_fileoff_t last;
803 uint lock_mode;
804
805 quotip = xfs_quota_inode(mp, type);
806 lock_mode = xfs_ilock_data_map_shared(quotip);
807 error = xfs_bmap_last_offset(quotip, &last, XFS_DATA_FORK);
808 xfs_iunlock(quotip, lock_mode);
809 if (error)
810 return error;
811 eof = XFS_FSB_TO_B(mp, last);
812 }
813
814restart: 792restart:
815 mutex_lock(&qi->qi_tree_lock); 793 mutex_lock(&qi->qi_tree_lock);
816 dqp = radix_tree_lookup(tree, id); 794 dqp = radix_tree_lookup(tree, id);
@@ -829,7 +807,7 @@ restart:
829 if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) { 807 if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
830 xfs_dqunlock(dqp); 808 xfs_dqunlock(dqp);
831 mutex_unlock(&qi->qi_tree_lock); 809 mutex_unlock(&qi->qi_tree_lock);
832 error = xfs_dq_get_next_id(mp, type, &id, eof); 810 error = xfs_dq_get_next_id(mp, type, &id);
833 if (error) 811 if (error)
834 return error; 812 return error;
835 goto restart; 813 goto restart;
@@ -864,7 +842,7 @@ restart:
864 842
865 /* If we are asked to find next active id, keep looking */ 843 /* If we are asked to find next active id, keep looking */
866 if (error == -ENOENT && (flags & XFS_QMOPT_DQNEXT)) { 844 if (error == -ENOENT && (flags & XFS_QMOPT_DQNEXT)) {
867 error = xfs_dq_get_next_id(mp, type, &id, eof); 845 error = xfs_dq_get_next_id(mp, type, &id);
868 if (!error) 846 if (!error)
869 goto restart; 847 goto restart;
870 } 848 }
@@ -923,7 +901,7 @@ restart:
923 if (flags & XFS_QMOPT_DQNEXT) { 901 if (flags & XFS_QMOPT_DQNEXT) {
924 if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) { 902 if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
925 xfs_qm_dqput(dqp); 903 xfs_qm_dqput(dqp);
926 error = xfs_dq_get_next_id(mp, type, &id, eof); 904 error = xfs_dq_get_next_id(mp, type, &id);
927 if (error) 905 if (error)
928 return error; 906 return error;
929 goto restart; 907 goto restart;