diff options
Diffstat (limited to 'fs/xfs/xfs_qm.c')
-rw-r--r-- | fs/xfs/xfs_qm.c | 243 |
1 files changed, 174 insertions, 69 deletions
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 7a3e007b49f4..d320794d03ce 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c | |||
@@ -137,6 +137,7 @@ xfs_qm_dqpurge( | |||
137 | struct xfs_mount *mp = dqp->q_mount; | 137 | struct xfs_mount *mp = dqp->q_mount; |
138 | struct xfs_quotainfo *qi = mp->m_quotainfo; | 138 | struct xfs_quotainfo *qi = mp->m_quotainfo; |
139 | struct xfs_dquot *gdqp = NULL; | 139 | struct xfs_dquot *gdqp = NULL; |
140 | struct xfs_dquot *pdqp = NULL; | ||
140 | 141 | ||
141 | xfs_dqlock(dqp); | 142 | xfs_dqlock(dqp); |
142 | if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) { | 143 | if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) { |
@@ -145,8 +146,7 @@ xfs_qm_dqpurge( | |||
145 | } | 146 | } |
146 | 147 | ||
147 | /* | 148 | /* |
148 | * If this quota has a group hint attached, prepare for releasing it | 149 | * If this quota has a hint attached, prepare for releasing it now. |
149 | * now. | ||
150 | */ | 150 | */ |
151 | gdqp = dqp->q_gdquot; | 151 | gdqp = dqp->q_gdquot; |
152 | if (gdqp) { | 152 | if (gdqp) { |
@@ -154,6 +154,12 @@ xfs_qm_dqpurge( | |||
154 | dqp->q_gdquot = NULL; | 154 | dqp->q_gdquot = NULL; |
155 | } | 155 | } |
156 | 156 | ||
157 | pdqp = dqp->q_pdquot; | ||
158 | if (pdqp) { | ||
159 | xfs_dqlock(pdqp); | ||
160 | dqp->q_pdquot = NULL; | ||
161 | } | ||
162 | |||
157 | dqp->dq_flags |= XFS_DQ_FREEING; | 163 | dqp->dq_flags |= XFS_DQ_FREEING; |
158 | 164 | ||
159 | xfs_dqflock(dqp); | 165 | xfs_dqflock(dqp); |
@@ -208,6 +214,8 @@ xfs_qm_dqpurge( | |||
208 | 214 | ||
209 | if (gdqp) | 215 | if (gdqp) |
210 | xfs_qm_dqput(gdqp); | 216 | xfs_qm_dqput(gdqp); |
217 | if (pdqp) | ||
218 | xfs_qm_dqput(pdqp); | ||
211 | return 0; | 219 | return 0; |
212 | } | 220 | } |
213 | 221 | ||
@@ -364,6 +372,10 @@ xfs_qm_unmount_quotas( | |||
364 | IRELE(mp->m_quotainfo->qi_gquotaip); | 372 | IRELE(mp->m_quotainfo->qi_gquotaip); |
365 | mp->m_quotainfo->qi_gquotaip = NULL; | 373 | mp->m_quotainfo->qi_gquotaip = NULL; |
366 | } | 374 | } |
375 | if (mp->m_quotainfo->qi_pquotaip) { | ||
376 | IRELE(mp->m_quotainfo->qi_pquotaip); | ||
377 | mp->m_quotainfo->qi_pquotaip = NULL; | ||
378 | } | ||
367 | } | 379 | } |
368 | } | 380 | } |
369 | 381 | ||
@@ -410,7 +422,10 @@ xfs_qm_dqattach_one( | |||
410 | * be reclaimed as long as we have a ref from inode and we | 422 | * be reclaimed as long as we have a ref from inode and we |
411 | * hold the ilock. | 423 | * hold the ilock. |
412 | */ | 424 | */ |
413 | dqp = udqhint->q_gdquot; | 425 | if (type == XFS_DQ_GROUP) |
426 | dqp = udqhint->q_gdquot; | ||
427 | else | ||
428 | dqp = udqhint->q_pdquot; | ||
414 | if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) { | 429 | if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) { |
415 | ASSERT(*IO_idqpp == NULL); | 430 | ASSERT(*IO_idqpp == NULL); |
416 | 431 | ||
@@ -453,28 +468,42 @@ xfs_qm_dqattach_one( | |||
453 | 468 | ||
454 | 469 | ||
455 | /* | 470 | /* |
456 | * Given a udquot and gdquot, attach a ptr to the group dquot in the | 471 | * Given a udquot and group/project type, attach the group/project |
457 | * udquot as a hint for future lookups. | 472 | * dquot pointer to the udquot as a hint for future lookups. |
458 | */ | 473 | */ |
459 | STATIC void | 474 | STATIC void |
460 | xfs_qm_dqattach_grouphint( | 475 | xfs_qm_dqattach_hint( |
461 | xfs_dquot_t *udq, | 476 | struct xfs_inode *ip, |
462 | xfs_dquot_t *gdq) | 477 | int type) |
463 | { | 478 | { |
464 | xfs_dquot_t *tmp; | 479 | struct xfs_dquot **dqhintp; |
480 | struct xfs_dquot *dqp; | ||
481 | struct xfs_dquot *udq = ip->i_udquot; | ||
482 | |||
483 | ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ); | ||
465 | 484 | ||
466 | xfs_dqlock(udq); | 485 | xfs_dqlock(udq); |
467 | 486 | ||
468 | tmp = udq->q_gdquot; | 487 | if (type == XFS_DQ_GROUP) { |
469 | if (tmp) { | 488 | dqp = ip->i_gdquot; |
470 | if (tmp == gdq) | 489 | dqhintp = &udq->q_gdquot; |
490 | } else { | ||
491 | dqp = ip->i_pdquot; | ||
492 | dqhintp = &udq->q_pdquot; | ||
493 | } | ||
494 | |||
495 | if (*dqhintp) { | ||
496 | struct xfs_dquot *tmp; | ||
497 | |||
498 | if (*dqhintp == dqp) | ||
471 | goto done; | 499 | goto done; |
472 | 500 | ||
473 | udq->q_gdquot = NULL; | 501 | tmp = *dqhintp; |
502 | *dqhintp = NULL; | ||
474 | xfs_qm_dqrele(tmp); | 503 | xfs_qm_dqrele(tmp); |
475 | } | 504 | } |
476 | 505 | ||
477 | udq->q_gdquot = xfs_qm_dqhold(gdq); | 506 | *dqhintp = xfs_qm_dqhold(dqp); |
478 | done: | 507 | done: |
479 | xfs_dqunlock(udq); | 508 | xfs_dqunlock(udq); |
480 | } | 509 | } |
@@ -527,12 +556,8 @@ xfs_qm_dqattach_locked( | |||
527 | } | 556 | } |
528 | 557 | ||
529 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 558 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
530 | if (XFS_IS_OQUOTA_ON(mp)) { | 559 | if (XFS_IS_GQUOTA_ON(mp)) { |
531 | error = XFS_IS_GQUOTA_ON(mp) ? | 560 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, |
532 | xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, | ||
533 | flags & XFS_QMOPT_DQALLOC, | ||
534 | ip->i_udquot, &ip->i_gdquot) : | ||
535 | xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ, | ||
536 | flags & XFS_QMOPT_DQALLOC, | 561 | flags & XFS_QMOPT_DQALLOC, |
537 | ip->i_udquot, &ip->i_gdquot); | 562 | ip->i_udquot, &ip->i_gdquot); |
538 | /* | 563 | /* |
@@ -544,14 +569,28 @@ xfs_qm_dqattach_locked( | |||
544 | nquotas++; | 569 | nquotas++; |
545 | } | 570 | } |
546 | 571 | ||
572 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
573 | if (XFS_IS_PQUOTA_ON(mp)) { | ||
574 | error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ, | ||
575 | flags & XFS_QMOPT_DQALLOC, | ||
576 | ip->i_udquot, &ip->i_pdquot); | ||
577 | /* | ||
578 | * Don't worry about the udquot that we may have | ||
579 | * attached above. It'll get detached, if not already. | ||
580 | */ | ||
581 | if (error) | ||
582 | goto done; | ||
583 | nquotas++; | ||
584 | } | ||
585 | |||
547 | /* | 586 | /* |
548 | * Attach this group quota to the user quota as a hint. | 587 | * Attach this group/project quota to the user quota as a hint. |
549 | * This WON'T, in general, result in a thrash. | 588 | * This WON'T, in general, result in a thrash. |
550 | */ | 589 | */ |
551 | if (nquotas == 2) { | 590 | if (nquotas > 1 && ip->i_udquot) { |
552 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 591 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
553 | ASSERT(ip->i_udquot); | 592 | ASSERT(ip->i_gdquot || !XFS_IS_GQUOTA_ON(mp)); |
554 | ASSERT(ip->i_gdquot); | 593 | ASSERT(ip->i_pdquot || !XFS_IS_PQUOTA_ON(mp)); |
555 | 594 | ||
556 | /* | 595 | /* |
557 | * We do not have i_udquot locked at this point, but this check | 596 | * We do not have i_udquot locked at this point, but this check |
@@ -560,7 +599,10 @@ xfs_qm_dqattach_locked( | |||
560 | * succeed in general. | 599 | * succeed in general. |
561 | */ | 600 | */ |
562 | if (ip->i_udquot->q_gdquot != ip->i_gdquot) | 601 | if (ip->i_udquot->q_gdquot != ip->i_gdquot) |
563 | xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); | 602 | xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP); |
603 | |||
604 | if (ip->i_udquot->q_pdquot != ip->i_pdquot) | ||
605 | xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ); | ||
564 | } | 606 | } |
565 | 607 | ||
566 | done: | 608 | done: |
@@ -568,8 +610,10 @@ xfs_qm_dqattach_locked( | |||
568 | if (!error) { | 610 | if (!error) { |
569 | if (XFS_IS_UQUOTA_ON(mp)) | 611 | if (XFS_IS_UQUOTA_ON(mp)) |
570 | ASSERT(ip->i_udquot); | 612 | ASSERT(ip->i_udquot); |
571 | if (XFS_IS_OQUOTA_ON(mp)) | 613 | if (XFS_IS_GQUOTA_ON(mp)) |
572 | ASSERT(ip->i_gdquot); | 614 | ASSERT(ip->i_gdquot); |
615 | if (XFS_IS_PQUOTA_ON(mp)) | ||
616 | ASSERT(ip->i_pdquot); | ||
573 | } | 617 | } |
574 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 618 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
575 | #endif | 619 | #endif |
@@ -602,7 +646,7 @@ void | |||
602 | xfs_qm_dqdetach( | 646 | xfs_qm_dqdetach( |
603 | xfs_inode_t *ip) | 647 | xfs_inode_t *ip) |
604 | { | 648 | { |
605 | if (!(ip->i_udquot || ip->i_gdquot)) | 649 | if (!(ip->i_udquot || ip->i_gdquot || ip->i_pdquot)) |
606 | return; | 650 | return; |
607 | 651 | ||
608 | trace_xfs_dquot_dqdetach(ip); | 652 | trace_xfs_dquot_dqdetach(ip); |
@@ -616,6 +660,10 @@ xfs_qm_dqdetach( | |||
616 | xfs_qm_dqrele(ip->i_gdquot); | 660 | xfs_qm_dqrele(ip->i_gdquot); |
617 | ip->i_gdquot = NULL; | 661 | ip->i_gdquot = NULL; |
618 | } | 662 | } |
663 | if (ip->i_pdquot) { | ||
664 | xfs_qm_dqrele(ip->i_pdquot); | ||
665 | ip->i_pdquot = NULL; | ||
666 | } | ||
619 | } | 667 | } |
620 | 668 | ||
621 | int | 669 | int |
@@ -660,6 +708,7 @@ xfs_qm_init_quotainfo( | |||
660 | 708 | ||
661 | INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS); | 709 | INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS); |
662 | INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS); | 710 | INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS); |
711 | INIT_RADIX_TREE(&qinf->qi_pquota_tree, GFP_NOFS); | ||
663 | mutex_init(&qinf->qi_tree_lock); | 712 | mutex_init(&qinf->qi_tree_lock); |
664 | 713 | ||
665 | INIT_LIST_HEAD(&qinf->qi_lru_list); | 714 | INIT_LIST_HEAD(&qinf->qi_lru_list); |
@@ -761,6 +810,10 @@ xfs_qm_destroy_quotainfo( | |||
761 | IRELE(qi->qi_gquotaip); | 810 | IRELE(qi->qi_gquotaip); |
762 | qi->qi_gquotaip = NULL; | 811 | qi->qi_gquotaip = NULL; |
763 | } | 812 | } |
813 | if (qi->qi_pquotaip) { | ||
814 | IRELE(qi->qi_pquotaip); | ||
815 | qi->qi_pquotaip = NULL; | ||
816 | } | ||
764 | mutex_destroy(&qi->qi_quotaofflock); | 817 | mutex_destroy(&qi->qi_quotaofflock); |
765 | kmem_free(qi); | 818 | kmem_free(qi); |
766 | mp->m_quotainfo = NULL; | 819 | mp->m_quotainfo = NULL; |
@@ -1269,13 +1322,14 @@ xfs_qm_quotacheck( | |||
1269 | LIST_HEAD (buffer_list); | 1322 | LIST_HEAD (buffer_list); |
1270 | struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip; | 1323 | struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip; |
1271 | struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip; | 1324 | struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip; |
1325 | struct xfs_inode *pip = mp->m_quotainfo->qi_pquotaip; | ||
1272 | 1326 | ||
1273 | count = INT_MAX; | 1327 | count = INT_MAX; |
1274 | structsz = 1; | 1328 | structsz = 1; |
1275 | lastino = 0; | 1329 | lastino = 0; |
1276 | flags = 0; | 1330 | flags = 0; |
1277 | 1331 | ||
1278 | ASSERT(uip || gip); | 1332 | ASSERT(uip || gip || pip); |
1279 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); | 1333 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); |
1280 | 1334 | ||
1281 | xfs_notice(mp, "Quotacheck needed: Please wait."); | 1335 | xfs_notice(mp, "Quotacheck needed: Please wait."); |
@@ -1294,13 +1348,19 @@ xfs_qm_quotacheck( | |||
1294 | } | 1348 | } |
1295 | 1349 | ||
1296 | if (gip) { | 1350 | if (gip) { |
1297 | error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ? | 1351 | error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA, |
1298 | XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA, | ||
1299 | &buffer_list); | 1352 | &buffer_list); |
1300 | if (error) | 1353 | if (error) |
1301 | goto error_return; | 1354 | goto error_return; |
1302 | flags |= XFS_IS_GQUOTA_ON(mp) ? | 1355 | flags |= XFS_GQUOTA_CHKD; |
1303 | XFS_GQUOTA_CHKD : XFS_PQUOTA_CHKD; | 1356 | } |
1357 | |||
1358 | if (pip) { | ||
1359 | error = xfs_qm_dqiterate(mp, pip, XFS_QMOPT_PQUOTA, | ||
1360 | &buffer_list); | ||
1361 | if (error) | ||
1362 | goto error_return; | ||
1363 | flags |= XFS_PQUOTA_CHKD; | ||
1304 | } | 1364 | } |
1305 | 1365 | ||
1306 | do { | 1366 | do { |
@@ -1397,6 +1457,7 @@ xfs_qm_init_quotainos( | |||
1397 | { | 1457 | { |
1398 | struct xfs_inode *uip = NULL; | 1458 | struct xfs_inode *uip = NULL; |
1399 | struct xfs_inode *gip = NULL; | 1459 | struct xfs_inode *gip = NULL; |
1460 | struct xfs_inode *pip = NULL; | ||
1400 | int error; | 1461 | int error; |
1401 | __int64_t sbflags = 0; | 1462 | __int64_t sbflags = 0; |
1402 | uint flags = 0; | 1463 | uint flags = 0; |
@@ -1415,7 +1476,7 @@ xfs_qm_init_quotainos( | |||
1415 | if (error) | 1476 | if (error) |
1416 | return XFS_ERROR(error); | 1477 | return XFS_ERROR(error); |
1417 | } | 1478 | } |
1418 | if (XFS_IS_OQUOTA_ON(mp) && | 1479 | if (XFS_IS_GQUOTA_ON(mp) && |
1419 | mp->m_sb.sb_gquotino != NULLFSINO) { | 1480 | mp->m_sb.sb_gquotino != NULLFSINO) { |
1420 | ASSERT(mp->m_sb.sb_gquotino > 0); | 1481 | ASSERT(mp->m_sb.sb_gquotino > 0); |
1421 | error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, | 1482 | error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, |
@@ -1423,6 +1484,15 @@ xfs_qm_init_quotainos( | |||
1423 | if (error) | 1484 | if (error) |
1424 | goto error_rele; | 1485 | goto error_rele; |
1425 | } | 1486 | } |
1487 | /* XXX: Use gquotino for now */ | ||
1488 | if (XFS_IS_PQUOTA_ON(mp) && | ||
1489 | mp->m_sb.sb_gquotino != NULLFSINO) { | ||
1490 | ASSERT(mp->m_sb.sb_gquotino > 0); | ||
1491 | error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, | ||
1492 | 0, 0, &pip); | ||
1493 | if (error) | ||
1494 | goto error_rele; | ||
1495 | } | ||
1426 | } else { | 1496 | } else { |
1427 | flags |= XFS_QMOPT_SBVERSION; | 1497 | flags |= XFS_QMOPT_SBVERSION; |
1428 | sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | | 1498 | sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | |
@@ -1430,7 +1500,7 @@ xfs_qm_init_quotainos( | |||
1430 | } | 1500 | } |
1431 | 1501 | ||
1432 | /* | 1502 | /* |
1433 | * Create the two inodes, if they don't exist already. The changes | 1503 | * Create the three inodes, if they don't exist already. The changes |
1434 | * made above will get added to a transaction and logged in one of | 1504 | * made above will get added to a transaction and logged in one of |
1435 | * the qino_alloc calls below. If the device is readonly, | 1505 | * the qino_alloc calls below. If the device is readonly, |
1436 | * temporarily switch to read-write to do this. | 1506 | * temporarily switch to read-write to do this. |
@@ -1444,17 +1514,27 @@ xfs_qm_init_quotainos( | |||
1444 | 1514 | ||
1445 | flags &= ~XFS_QMOPT_SBVERSION; | 1515 | flags &= ~XFS_QMOPT_SBVERSION; |
1446 | } | 1516 | } |
1447 | if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) { | 1517 | if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) { |
1448 | flags |= (XFS_IS_GQUOTA_ON(mp) ? | ||
1449 | XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA); | ||
1450 | error = xfs_qm_qino_alloc(mp, &gip, | 1518 | error = xfs_qm_qino_alloc(mp, &gip, |
1451 | sbflags | XFS_SB_GQUOTINO, flags); | 1519 | sbflags | XFS_SB_GQUOTINO, |
1520 | flags | XFS_QMOPT_GQUOTA); | ||
1521 | if (error) | ||
1522 | goto error_rele; | ||
1523 | |||
1524 | flags &= ~XFS_QMOPT_SBVERSION; | ||
1525 | } | ||
1526 | if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) { | ||
1527 | /* XXX: Use XFS_SB_GQUOTINO for now */ | ||
1528 | error = xfs_qm_qino_alloc(mp, &pip, | ||
1529 | sbflags | XFS_SB_GQUOTINO, | ||
1530 | flags | XFS_QMOPT_PQUOTA); | ||
1452 | if (error) | 1531 | if (error) |
1453 | goto error_rele; | 1532 | goto error_rele; |
1454 | } | 1533 | } |
1455 | 1534 | ||
1456 | mp->m_quotainfo->qi_uquotaip = uip; | 1535 | mp->m_quotainfo->qi_uquotaip = uip; |
1457 | mp->m_quotainfo->qi_gquotaip = gip; | 1536 | mp->m_quotainfo->qi_gquotaip = gip; |
1537 | mp->m_quotainfo->qi_pquotaip = pip; | ||
1458 | 1538 | ||
1459 | return 0; | 1539 | return 0; |
1460 | 1540 | ||
@@ -1463,6 +1543,8 @@ error_rele: | |||
1463 | IRELE(uip); | 1543 | IRELE(uip); |
1464 | if (gip) | 1544 | if (gip) |
1465 | IRELE(gip); | 1545 | IRELE(gip); |
1546 | if (pip) | ||
1547 | IRELE(pip); | ||
1466 | return XFS_ERROR(error); | 1548 | return XFS_ERROR(error); |
1467 | } | 1549 | } |
1468 | 1550 | ||
@@ -1657,11 +1739,13 @@ xfs_qm_vop_dqalloc( | |||
1657 | prid_t prid, | 1739 | prid_t prid, |
1658 | uint flags, | 1740 | uint flags, |
1659 | struct xfs_dquot **O_udqpp, | 1741 | struct xfs_dquot **O_udqpp, |
1660 | struct xfs_dquot **O_gdqpp) | 1742 | struct xfs_dquot **O_gdqpp, |
1743 | struct xfs_dquot **O_pdqpp) | ||
1661 | { | 1744 | { |
1662 | struct xfs_mount *mp = ip->i_mount; | 1745 | struct xfs_mount *mp = ip->i_mount; |
1663 | struct xfs_dquot *uq = NULL; | 1746 | struct xfs_dquot *uq = NULL; |
1664 | struct xfs_dquot *gq = NULL; | 1747 | struct xfs_dquot *gq = NULL; |
1748 | struct xfs_dquot *pq = NULL; | ||
1665 | int error; | 1749 | int error; |
1666 | uint lockflags; | 1750 | uint lockflags; |
1667 | 1751 | ||
@@ -1741,24 +1825,25 @@ xfs_qm_vop_dqalloc( | |||
1741 | ASSERT(ip->i_gdquot); | 1825 | ASSERT(ip->i_gdquot); |
1742 | gq = xfs_qm_dqhold(ip->i_gdquot); | 1826 | gq = xfs_qm_dqhold(ip->i_gdquot); |
1743 | } | 1827 | } |
1744 | } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { | 1828 | } |
1829 | if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { | ||
1745 | if (xfs_get_projid(ip) != prid) { | 1830 | if (xfs_get_projid(ip) != prid) { |
1746 | xfs_iunlock(ip, lockflags); | 1831 | xfs_iunlock(ip, lockflags); |
1747 | error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, | 1832 | error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, |
1748 | XFS_DQ_PROJ, | 1833 | XFS_DQ_PROJ, |
1749 | XFS_QMOPT_DQALLOC | | 1834 | XFS_QMOPT_DQALLOC | |
1750 | XFS_QMOPT_DOWARN, | 1835 | XFS_QMOPT_DOWARN, |
1751 | &gq); | 1836 | &pq); |
1752 | if (error) { | 1837 | if (error) { |
1753 | ASSERT(error != ENOENT); | 1838 | ASSERT(error != ENOENT); |
1754 | goto error_rele; | 1839 | goto error_rele; |
1755 | } | 1840 | } |
1756 | xfs_dqunlock(gq); | 1841 | xfs_dqunlock(pq); |
1757 | lockflags = XFS_ILOCK_SHARED; | 1842 | lockflags = XFS_ILOCK_SHARED; |
1758 | xfs_ilock(ip, lockflags); | 1843 | xfs_ilock(ip, lockflags); |
1759 | } else { | 1844 | } else { |
1760 | ASSERT(ip->i_gdquot); | 1845 | ASSERT(ip->i_pdquot); |
1761 | gq = xfs_qm_dqhold(ip->i_gdquot); | 1846 | pq = xfs_qm_dqhold(ip->i_pdquot); |
1762 | } | 1847 | } |
1763 | } | 1848 | } |
1764 | if (uq) | 1849 | if (uq) |
@@ -1773,9 +1858,15 @@ xfs_qm_vop_dqalloc( | |||
1773 | *O_gdqpp = gq; | 1858 | *O_gdqpp = gq; |
1774 | else if (gq) | 1859 | else if (gq) |
1775 | xfs_qm_dqrele(gq); | 1860 | xfs_qm_dqrele(gq); |
1861 | if (O_pdqpp) | ||
1862 | *O_pdqpp = pq; | ||
1863 | else if (pq) | ||
1864 | xfs_qm_dqrele(pq); | ||
1776 | return 0; | 1865 | return 0; |
1777 | 1866 | ||
1778 | error_rele: | 1867 | error_rele: |
1868 | if (gq) | ||
1869 | xfs_qm_dqrele(gq); | ||
1779 | if (uq) | 1870 | if (uq) |
1780 | xfs_qm_dqrele(uq); | 1871 | xfs_qm_dqrele(uq); |
1781 | return error; | 1872 | return error; |
@@ -1830,14 +1921,17 @@ xfs_qm_vop_chown_reserve( | |||
1830 | struct xfs_inode *ip, | 1921 | struct xfs_inode *ip, |
1831 | struct xfs_dquot *udqp, | 1922 | struct xfs_dquot *udqp, |
1832 | struct xfs_dquot *gdqp, | 1923 | struct xfs_dquot *gdqp, |
1924 | struct xfs_dquot *pdqp, | ||
1833 | uint flags) | 1925 | uint flags) |
1834 | { | 1926 | { |
1835 | struct xfs_mount *mp = ip->i_mount; | 1927 | struct xfs_mount *mp = ip->i_mount; |
1836 | uint delblks, blkflags, prjflags = 0; | 1928 | uint delblks, blkflags, prjflags = 0; |
1837 | struct xfs_dquot *udq_unres = NULL; | 1929 | struct xfs_dquot *udq_unres = NULL; |
1838 | struct xfs_dquot *gdq_unres = NULL; | 1930 | struct xfs_dquot *gdq_unres = NULL; |
1931 | struct xfs_dquot *pdq_unres = NULL; | ||
1839 | struct xfs_dquot *udq_delblks = NULL; | 1932 | struct xfs_dquot *udq_delblks = NULL; |
1840 | struct xfs_dquot *gdq_delblks = NULL; | 1933 | struct xfs_dquot *gdq_delblks = NULL; |
1934 | struct xfs_dquot *pdq_delblks = NULL; | ||
1841 | int error; | 1935 | int error; |
1842 | 1936 | ||
1843 | 1937 | ||
@@ -1861,24 +1955,28 @@ xfs_qm_vop_chown_reserve( | |||
1861 | udq_unres = ip->i_udquot; | 1955 | udq_unres = ip->i_udquot; |
1862 | } | 1956 | } |
1863 | } | 1957 | } |
1864 | if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { | 1958 | if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp && |
1865 | if (XFS_IS_PQUOTA_ON(ip->i_mount) && | 1959 | ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) { |
1866 | xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id)) | 1960 | gdq_delblks = gdqp; |
1867 | prjflags = XFS_QMOPT_ENOSPC; | 1961 | if (delblks) { |
1868 | 1962 | ASSERT(ip->i_gdquot); | |
1869 | if (prjflags || | 1963 | gdq_unres = ip->i_gdquot; |
1870 | (XFS_IS_GQUOTA_ON(ip->i_mount) && | 1964 | } |
1871 | ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) { | 1965 | } |
1872 | gdq_delblks = gdqp; | 1966 | |
1873 | if (delblks) { | 1967 | if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp && |
1874 | ASSERT(ip->i_gdquot); | 1968 | xfs_get_projid(ip) != be32_to_cpu(pdqp->q_core.d_id)) { |
1875 | gdq_unres = ip->i_gdquot; | 1969 | prjflags = XFS_QMOPT_ENOSPC; |
1876 | } | 1970 | pdq_delblks = pdqp; |
1971 | if (delblks) { | ||
1972 | ASSERT(ip->i_pdquot); | ||
1973 | pdq_unres = ip->i_pdquot; | ||
1877 | } | 1974 | } |
1878 | } | 1975 | } |
1879 | 1976 | ||
1880 | error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, | 1977 | error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, |
1881 | udq_delblks, gdq_delblks, ip->i_d.di_nblocks, 1, | 1978 | udq_delblks, gdq_delblks, pdq_delblks, |
1979 | ip->i_d.di_nblocks, 1, | ||
1882 | flags | blkflags | prjflags); | 1980 | flags | blkflags | prjflags); |
1883 | if (error) | 1981 | if (error) |
1884 | return error; | 1982 | return error; |
@@ -1893,16 +1991,17 @@ xfs_qm_vop_chown_reserve( | |||
1893 | /* | 1991 | /* |
1894 | * Do the reservations first. Unreservation can't fail. | 1992 | * Do the reservations first. Unreservation can't fail. |
1895 | */ | 1993 | */ |
1896 | ASSERT(udq_delblks || gdq_delblks); | 1994 | ASSERT(udq_delblks || gdq_delblks || pdq_delblks); |
1897 | ASSERT(udq_unres || gdq_unres); | 1995 | ASSERT(udq_unres || gdq_unres || pdq_unres); |
1898 | error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, | 1996 | error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, |
1899 | udq_delblks, gdq_delblks, (xfs_qcnt_t)delblks, 0, | 1997 | udq_delblks, gdq_delblks, pdq_delblks, |
1998 | (xfs_qcnt_t)delblks, 0, | ||
1900 | flags | blkflags | prjflags); | 1999 | flags | blkflags | prjflags); |
1901 | if (error) | 2000 | if (error) |
1902 | return error; | 2001 | return error; |
1903 | xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, | 2002 | xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, |
1904 | udq_unres, gdq_unres, -((xfs_qcnt_t)delblks), 0, | 2003 | udq_unres, gdq_unres, pdq_unres, |
1905 | blkflags); | 2004 | -((xfs_qcnt_t)delblks), 0, blkflags); |
1906 | } | 2005 | } |
1907 | 2006 | ||
1908 | return (0); | 2007 | return (0); |
@@ -1941,7 +2040,8 @@ xfs_qm_vop_create_dqattach( | |||
1941 | struct xfs_trans *tp, | 2040 | struct xfs_trans *tp, |
1942 | struct xfs_inode *ip, | 2041 | struct xfs_inode *ip, |
1943 | struct xfs_dquot *udqp, | 2042 | struct xfs_dquot *udqp, |
1944 | struct xfs_dquot *gdqp) | 2043 | struct xfs_dquot *gdqp, |
2044 | struct xfs_dquot *pdqp) | ||
1945 | { | 2045 | { |
1946 | struct xfs_mount *mp = tp->t_mountp; | 2046 | struct xfs_mount *mp = tp->t_mountp; |
1947 | 2047 | ||
@@ -1961,13 +2061,18 @@ xfs_qm_vop_create_dqattach( | |||
1961 | } | 2061 | } |
1962 | if (gdqp) { | 2062 | if (gdqp) { |
1963 | ASSERT(ip->i_gdquot == NULL); | 2063 | ASSERT(ip->i_gdquot == NULL); |
1964 | ASSERT(XFS_IS_OQUOTA_ON(mp)); | 2064 | ASSERT(XFS_IS_GQUOTA_ON(mp)); |
1965 | ASSERT((XFS_IS_GQUOTA_ON(mp) ? | 2065 | ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id)); |
1966 | ip->i_d.di_gid : xfs_get_projid(ip)) == | ||
1967 | be32_to_cpu(gdqp->q_core.d_id)); | ||
1968 | |||
1969 | ip->i_gdquot = xfs_qm_dqhold(gdqp); | 2066 | ip->i_gdquot = xfs_qm_dqhold(gdqp); |
1970 | xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); | 2067 | xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); |
1971 | } | 2068 | } |
2069 | if (pdqp) { | ||
2070 | ASSERT(ip->i_pdquot == NULL); | ||
2071 | ASSERT(XFS_IS_PQUOTA_ON(mp)); | ||
2072 | ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id)); | ||
2073 | |||
2074 | ip->i_pdquot = xfs_qm_dqhold(pdqp); | ||
2075 | xfs_trans_mod_dquot(tp, pdqp, XFS_TRANS_DQ_ICOUNT, 1); | ||
2076 | } | ||
1972 | } | 2077 | } |
1973 | 2078 | ||