diff options
Diffstat (limited to 'fs/xfs/quota/xfs_qm.c')
-rw-r--r-- | fs/xfs/quota/xfs_qm.c | 168 |
1 files changed, 78 insertions, 90 deletions
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 5b6695049e00..45b1bfef7388 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include "xfs_error.h" | 42 | #include "xfs_error.h" |
43 | #include "xfs_bmap.h" | 43 | #include "xfs_bmap.h" |
44 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
45 | #include "xfs_acl.h" | ||
46 | #include "xfs_attr.h" | 45 | #include "xfs_attr.h" |
47 | #include "xfs_buf_item.h" | 46 | #include "xfs_buf_item.h" |
48 | #include "xfs_trans_space.h" | 47 | #include "xfs_trans_space.h" |
@@ -287,11 +286,13 @@ xfs_qm_rele_quotafs_ref( | |||
287 | * Just destroy the quotainfo structure. | 286 | * Just destroy the quotainfo structure. |
288 | */ | 287 | */ |
289 | void | 288 | void |
290 | xfs_qm_unmount_quotadestroy( | 289 | xfs_qm_unmount( |
291 | xfs_mount_t *mp) | 290 | struct xfs_mount *mp) |
292 | { | 291 | { |
293 | if (mp->m_quotainfo) | 292 | if (mp->m_quotainfo) { |
293 | xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING); | ||
294 | xfs_qm_destroy_quotainfo(mp); | 294 | xfs_qm_destroy_quotainfo(mp); |
295 | } | ||
295 | } | 296 | } |
296 | 297 | ||
297 | 298 | ||
@@ -385,8 +386,13 @@ xfs_qm_mount_quotas( | |||
385 | if (error) { | 386 | if (error) { |
386 | xfs_fs_cmn_err(CE_WARN, mp, | 387 | xfs_fs_cmn_err(CE_WARN, mp, |
387 | "Failed to initialize disk quotas."); | 388 | "Failed to initialize disk quotas."); |
389 | return; | ||
388 | } | 390 | } |
389 | return; | 391 | |
392 | #ifdef QUOTADEBUG | ||
393 | if (XFS_IS_QUOTA_ON(mp)) | ||
394 | xfs_qm_internalqcheck(mp); | ||
395 | #endif | ||
390 | } | 396 | } |
391 | 397 | ||
392 | /* | 398 | /* |
@@ -774,12 +780,11 @@ xfs_qm_dqattach_grouphint( | |||
774 | * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON | 780 | * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON |
775 | * into account. | 781 | * into account. |
776 | * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed. | 782 | * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed. |
777 | * If XFS_QMOPT_ILOCKED, then inode sent is already locked EXCL. | ||
778 | * Inode may get unlocked and relocked in here, and the caller must deal with | 783 | * Inode may get unlocked and relocked in here, and the caller must deal with |
779 | * the consequences. | 784 | * the consequences. |
780 | */ | 785 | */ |
781 | int | 786 | int |
782 | xfs_qm_dqattach( | 787 | xfs_qm_dqattach_locked( |
783 | xfs_inode_t *ip, | 788 | xfs_inode_t *ip, |
784 | uint flags) | 789 | uint flags) |
785 | { | 790 | { |
@@ -787,17 +792,14 @@ xfs_qm_dqattach( | |||
787 | uint nquotas = 0; | 792 | uint nquotas = 0; |
788 | int error = 0; | 793 | int error = 0; |
789 | 794 | ||
790 | if ((! XFS_IS_QUOTA_ON(mp)) || | 795 | if (!XFS_IS_QUOTA_RUNNING(mp) || |
791 | (! XFS_NOT_DQATTACHED(mp, ip)) || | 796 | !XFS_IS_QUOTA_ON(mp) || |
792 | (ip->i_ino == mp->m_sb.sb_uquotino) || | 797 | !XFS_NOT_DQATTACHED(mp, ip) || |
793 | (ip->i_ino == mp->m_sb.sb_gquotino)) | 798 | ip->i_ino == mp->m_sb.sb_uquotino || |
799 | ip->i_ino == mp->m_sb.sb_gquotino) | ||
794 | return 0; | 800 | return 0; |
795 | 801 | ||
796 | ASSERT((flags & XFS_QMOPT_ILOCKED) == 0 || | 802 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
797 | xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
798 | |||
799 | if (! (flags & XFS_QMOPT_ILOCKED)) | ||
800 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
801 | 803 | ||
802 | if (XFS_IS_UQUOTA_ON(mp)) { | 804 | if (XFS_IS_UQUOTA_ON(mp)) { |
803 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, | 805 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, |
@@ -849,8 +851,7 @@ xfs_qm_dqattach( | |||
849 | xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); | 851 | xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); |
850 | } | 852 | } |
851 | 853 | ||
852 | done: | 854 | done: |
853 | |||
854 | #ifdef QUOTADEBUG | 855 | #ifdef QUOTADEBUG |
855 | if (! error) { | 856 | if (! error) { |
856 | if (XFS_IS_UQUOTA_ON(mp)) | 857 | if (XFS_IS_UQUOTA_ON(mp)) |
@@ -858,15 +859,22 @@ xfs_qm_dqattach( | |||
858 | if (XFS_IS_OQUOTA_ON(mp)) | 859 | if (XFS_IS_OQUOTA_ON(mp)) |
859 | ASSERT(ip->i_gdquot); | 860 | ASSERT(ip->i_gdquot); |
860 | } | 861 | } |
862 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
861 | #endif | 863 | #endif |
864 | return error; | ||
865 | } | ||
862 | 866 | ||
863 | if (! (flags & XFS_QMOPT_ILOCKED)) | 867 | int |
864 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 868 | xfs_qm_dqattach( |
869 | struct xfs_inode *ip, | ||
870 | uint flags) | ||
871 | { | ||
872 | int error; | ||
873 | |||
874 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
875 | error = xfs_qm_dqattach_locked(ip, flags); | ||
876 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
865 | 877 | ||
866 | #ifdef QUOTADEBUG | ||
867 | else | ||
868 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
869 | #endif | ||
870 | return error; | 878 | return error; |
871 | } | 879 | } |
872 | 880 | ||
@@ -896,11 +904,6 @@ xfs_qm_dqdetach( | |||
896 | } | 904 | } |
897 | } | 905 | } |
898 | 906 | ||
899 | /* | ||
900 | * This is called to sync quotas. We can be told to use non-blocking | ||
901 | * semantics by either the SYNC_BDFLUSH flag or the absence of the | ||
902 | * SYNC_WAIT flag. | ||
903 | */ | ||
904 | int | 907 | int |
905 | xfs_qm_sync( | 908 | xfs_qm_sync( |
906 | xfs_mount_t *mp, | 909 | xfs_mount_t *mp, |
@@ -909,17 +912,13 @@ xfs_qm_sync( | |||
909 | int recl, restarts; | 912 | int recl, restarts; |
910 | xfs_dquot_t *dqp; | 913 | xfs_dquot_t *dqp; |
911 | uint flush_flags; | 914 | uint flush_flags; |
912 | boolean_t nowait; | ||
913 | int error; | 915 | int error; |
914 | 916 | ||
915 | if (! XFS_IS_QUOTA_ON(mp)) | 917 | if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp)) |
916 | return 0; | 918 | return 0; |
917 | 919 | ||
920 | flush_flags = (flags & SYNC_WAIT) ? XFS_QMOPT_SYNC : XFS_QMOPT_DELWRI; | ||
918 | restarts = 0; | 921 | restarts = 0; |
919 | /* | ||
920 | * We won't block unless we are asked to. | ||
921 | */ | ||
922 | nowait = (boolean_t)(flags & SYNC_BDFLUSH || (flags & SYNC_WAIT) == 0); | ||
923 | 922 | ||
924 | again: | 923 | again: |
925 | xfs_qm_mplist_lock(mp); | 924 | xfs_qm_mplist_lock(mp); |
@@ -939,18 +938,10 @@ xfs_qm_sync( | |||
939 | * don't 'seem' to be dirty. ie. don't acquire dqlock. | 938 | * don't 'seem' to be dirty. ie. don't acquire dqlock. |
940 | * This is very similar to what xfs_sync does with inodes. | 939 | * This is very similar to what xfs_sync does with inodes. |
941 | */ | 940 | */ |
942 | if (flags & SYNC_BDFLUSH) { | 941 | if (flags & SYNC_TRYLOCK) { |
943 | if (! XFS_DQ_IS_DIRTY(dqp)) | 942 | if (!XFS_DQ_IS_DIRTY(dqp)) |
944 | continue; | 943 | continue; |
945 | } | 944 | if (!xfs_qm_dqlock_nowait(dqp)) |
946 | |||
947 | if (nowait) { | ||
948 | /* | ||
949 | * Try to acquire the dquot lock. We are NOT out of | ||
950 | * lock order, but we just don't want to wait for this | ||
951 | * lock, unless somebody wanted us to. | ||
952 | */ | ||
953 | if (! xfs_qm_dqlock_nowait(dqp)) | ||
954 | continue; | 945 | continue; |
955 | } else { | 946 | } else { |
956 | xfs_dqlock(dqp); | 947 | xfs_dqlock(dqp); |
@@ -967,7 +958,7 @@ xfs_qm_sync( | |||
967 | /* XXX a sentinel would be better */ | 958 | /* XXX a sentinel would be better */ |
968 | recl = XFS_QI_MPLRECLAIMS(mp); | 959 | recl = XFS_QI_MPLRECLAIMS(mp); |
969 | if (!xfs_dqflock_nowait(dqp)) { | 960 | if (!xfs_dqflock_nowait(dqp)) { |
970 | if (nowait) { | 961 | if (flags & SYNC_TRYLOCK) { |
971 | xfs_dqunlock(dqp); | 962 | xfs_dqunlock(dqp); |
972 | continue; | 963 | continue; |
973 | } | 964 | } |
@@ -985,7 +976,6 @@ xfs_qm_sync( | |||
985 | * Let go of the mplist lock. We don't want to hold it | 976 | * Let go of the mplist lock. We don't want to hold it |
986 | * across a disk write | 977 | * across a disk write |
987 | */ | 978 | */ |
988 | flush_flags = (nowait) ? XFS_QMOPT_DELWRI : XFS_QMOPT_SYNC; | ||
989 | xfs_qm_mplist_unlock(mp); | 979 | xfs_qm_mplist_unlock(mp); |
990 | xfs_dqtrace_entry(dqp, "XQM_SYNC: DQFLUSH"); | 980 | xfs_dqtrace_entry(dqp, "XQM_SYNC: DQFLUSH"); |
991 | error = xfs_qm_dqflush(dqp, flush_flags); | 981 | error = xfs_qm_dqflush(dqp, flush_flags); |
@@ -2319,20 +2309,20 @@ xfs_qm_write_sb_changes( | |||
2319 | */ | 2309 | */ |
2320 | int | 2310 | int |
2321 | xfs_qm_vop_dqalloc( | 2311 | xfs_qm_vop_dqalloc( |
2322 | xfs_mount_t *mp, | 2312 | struct xfs_inode *ip, |
2323 | xfs_inode_t *ip, | 2313 | uid_t uid, |
2324 | uid_t uid, | 2314 | gid_t gid, |
2325 | gid_t gid, | 2315 | prid_t prid, |
2326 | prid_t prid, | 2316 | uint flags, |
2327 | uint flags, | 2317 | struct xfs_dquot **O_udqpp, |
2328 | xfs_dquot_t **O_udqpp, | 2318 | struct xfs_dquot **O_gdqpp) |
2329 | xfs_dquot_t **O_gdqpp) | ||
2330 | { | 2319 | { |
2331 | int error; | 2320 | struct xfs_mount *mp = ip->i_mount; |
2332 | xfs_dquot_t *uq, *gq; | 2321 | struct xfs_dquot *uq, *gq; |
2333 | uint lockflags; | 2322 | int error; |
2323 | uint lockflags; | ||
2334 | 2324 | ||
2335 | if (!XFS_IS_QUOTA_ON(mp)) | 2325 | if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp)) |
2336 | return 0; | 2326 | return 0; |
2337 | 2327 | ||
2338 | lockflags = XFS_ILOCK_EXCL; | 2328 | lockflags = XFS_ILOCK_EXCL; |
@@ -2346,8 +2336,8 @@ xfs_qm_vop_dqalloc( | |||
2346 | * if necessary. The dquot(s) will not be locked. | 2336 | * if necessary. The dquot(s) will not be locked. |
2347 | */ | 2337 | */ |
2348 | if (XFS_NOT_DQATTACHED(mp, ip)) { | 2338 | if (XFS_NOT_DQATTACHED(mp, ip)) { |
2349 | if ((error = xfs_qm_dqattach(ip, XFS_QMOPT_DQALLOC | | 2339 | error = xfs_qm_dqattach_locked(ip, XFS_QMOPT_DQALLOC); |
2350 | XFS_QMOPT_ILOCKED))) { | 2340 | if (error) { |
2351 | xfs_iunlock(ip, lockflags); | 2341 | xfs_iunlock(ip, lockflags); |
2352 | return error; | 2342 | return error; |
2353 | } | 2343 | } |
@@ -2469,6 +2459,7 @@ xfs_qm_vop_chown( | |||
2469 | uint bfield = XFS_IS_REALTIME_INODE(ip) ? | 2459 | uint bfield = XFS_IS_REALTIME_INODE(ip) ? |
2470 | XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT; | 2460 | XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT; |
2471 | 2461 | ||
2462 | |||
2472 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 2463 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
2473 | ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount)); | 2464 | ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount)); |
2474 | 2465 | ||
@@ -2508,13 +2499,13 @@ xfs_qm_vop_chown_reserve( | |||
2508 | xfs_dquot_t *gdqp, | 2499 | xfs_dquot_t *gdqp, |
2509 | uint flags) | 2500 | uint flags) |
2510 | { | 2501 | { |
2511 | int error; | 2502 | xfs_mount_t *mp = ip->i_mount; |
2512 | xfs_mount_t *mp; | ||
2513 | uint delblks, blkflags, prjflags = 0; | 2503 | uint delblks, blkflags, prjflags = 0; |
2514 | xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; | 2504 | xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; |
2505 | int error; | ||
2506 | |||
2515 | 2507 | ||
2516 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); | 2508 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); |
2517 | mp = ip->i_mount; | ||
2518 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); | 2509 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); |
2519 | 2510 | ||
2520 | delblks = ip->i_delayed_blks; | 2511 | delblks = ip->i_delayed_blks; |
@@ -2582,28 +2573,23 @@ xfs_qm_vop_chown_reserve( | |||
2582 | 2573 | ||
2583 | int | 2574 | int |
2584 | xfs_qm_vop_rename_dqattach( | 2575 | xfs_qm_vop_rename_dqattach( |
2585 | xfs_inode_t **i_tab) | 2576 | struct xfs_inode **i_tab) |
2586 | { | 2577 | { |
2587 | xfs_inode_t *ip; | 2578 | struct xfs_mount *mp = i_tab[0]->i_mount; |
2588 | int i; | 2579 | int i; |
2589 | int error; | ||
2590 | 2580 | ||
2591 | ip = i_tab[0]; | 2581 | if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp)) |
2592 | |||
2593 | if (! XFS_IS_QUOTA_ON(ip->i_mount)) | ||
2594 | return 0; | 2582 | return 0; |
2595 | 2583 | ||
2596 | if (XFS_NOT_DQATTACHED(ip->i_mount, ip)) { | 2584 | for (i = 0; (i < 4 && i_tab[i]); i++) { |
2597 | error = xfs_qm_dqattach(ip, 0); | 2585 | struct xfs_inode *ip = i_tab[i]; |
2598 | if (error) | 2586 | int error; |
2599 | return error; | 2587 | |
2600 | } | ||
2601 | for (i = 1; (i < 4 && i_tab[i]); i++) { | ||
2602 | /* | 2588 | /* |
2603 | * Watch out for duplicate entries in the table. | 2589 | * Watch out for duplicate entries in the table. |
2604 | */ | 2590 | */ |
2605 | if ((ip = i_tab[i]) != i_tab[i-1]) { | 2591 | if (i == 0 || ip != i_tab[i-1]) { |
2606 | if (XFS_NOT_DQATTACHED(ip->i_mount, ip)) { | 2592 | if (XFS_NOT_DQATTACHED(mp, ip)) { |
2607 | error = xfs_qm_dqattach(ip, 0); | 2593 | error = xfs_qm_dqattach(ip, 0); |
2608 | if (error) | 2594 | if (error) |
2609 | return error; | 2595 | return error; |
@@ -2614,17 +2600,19 @@ xfs_qm_vop_rename_dqattach( | |||
2614 | } | 2600 | } |
2615 | 2601 | ||
2616 | void | 2602 | void |
2617 | xfs_qm_vop_dqattach_and_dqmod_newinode( | 2603 | xfs_qm_vop_create_dqattach( |
2618 | xfs_trans_t *tp, | 2604 | struct xfs_trans *tp, |
2619 | xfs_inode_t *ip, | 2605 | struct xfs_inode *ip, |
2620 | xfs_dquot_t *udqp, | 2606 | struct xfs_dquot *udqp, |
2621 | xfs_dquot_t *gdqp) | 2607 | struct xfs_dquot *gdqp) |
2622 | { | 2608 | { |
2623 | if (!XFS_IS_QUOTA_ON(tp->t_mountp)) | 2609 | struct xfs_mount *mp = tp->t_mountp; |
2610 | |||
2611 | if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp)) | ||
2624 | return; | 2612 | return; |
2625 | 2613 | ||
2626 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 2614 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
2627 | ASSERT(XFS_IS_QUOTA_RUNNING(tp->t_mountp)); | 2615 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); |
2628 | 2616 | ||
2629 | if (udqp) { | 2617 | if (udqp) { |
2630 | xfs_dqlock(udqp); | 2618 | xfs_dqlock(udqp); |
@@ -2632,7 +2620,7 @@ xfs_qm_vop_dqattach_and_dqmod_newinode( | |||
2632 | xfs_dqunlock(udqp); | 2620 | xfs_dqunlock(udqp); |
2633 | ASSERT(ip->i_udquot == NULL); | 2621 | ASSERT(ip->i_udquot == NULL); |
2634 | ip->i_udquot = udqp; | 2622 | ip->i_udquot = udqp; |
2635 | ASSERT(XFS_IS_UQUOTA_ON(tp->t_mountp)); | 2623 | ASSERT(XFS_IS_UQUOTA_ON(mp)); |
2636 | ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id)); | 2624 | ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id)); |
2637 | xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1); | 2625 | xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1); |
2638 | } | 2626 | } |
@@ -2642,8 +2630,8 @@ xfs_qm_vop_dqattach_and_dqmod_newinode( | |||
2642 | xfs_dqunlock(gdqp); | 2630 | xfs_dqunlock(gdqp); |
2643 | ASSERT(ip->i_gdquot == NULL); | 2631 | ASSERT(ip->i_gdquot == NULL); |
2644 | ip->i_gdquot = gdqp; | 2632 | ip->i_gdquot = gdqp; |
2645 | ASSERT(XFS_IS_OQUOTA_ON(tp->t_mountp)); | 2633 | ASSERT(XFS_IS_OQUOTA_ON(mp)); |
2646 | ASSERT((XFS_IS_GQUOTA_ON(tp->t_mountp) ? | 2634 | ASSERT((XFS_IS_GQUOTA_ON(mp) ? |
2647 | ip->i_d.di_gid : ip->i_d.di_projid) == | 2635 | ip->i_d.di_gid : ip->i_d.di_projid) == |
2648 | be32_to_cpu(gdqp->q_core.d_id)); | 2636 | be32_to_cpu(gdqp->q_core.d_id)); |
2649 | xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); | 2637 | xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); |