diff options
Diffstat (limited to 'fs/xfs/quota/xfs_dquot.c')
| -rw-r--r-- | fs/xfs/quota/xfs_dquot.c | 164 |
1 files changed, 76 insertions, 88 deletions
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index e1a2f6800e0..faf8e1a83a1 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c | |||
| @@ -463,87 +463,68 @@ xfs_qm_dqtobp( | |||
| 463 | uint flags) | 463 | uint flags) |
| 464 | { | 464 | { |
| 465 | xfs_bmbt_irec_t map; | 465 | xfs_bmbt_irec_t map; |
| 466 | int nmaps, error; | 466 | int nmaps = 1, error; |
| 467 | xfs_buf_t *bp; | 467 | xfs_buf_t *bp; |
| 468 | xfs_inode_t *quotip; | 468 | xfs_inode_t *quotip = XFS_DQ_TO_QIP(dqp); |
| 469 | xfs_mount_t *mp; | 469 | xfs_mount_t *mp = dqp->q_mount; |
| 470 | xfs_disk_dquot_t *ddq; | 470 | xfs_disk_dquot_t *ddq; |
| 471 | xfs_dqid_t id; | 471 | xfs_dqid_t id = be32_to_cpu(dqp->q_core.d_id); |
| 472 | boolean_t newdquot; | ||
| 473 | xfs_trans_t *tp = (tpp ? *tpp : NULL); | 472 | xfs_trans_t *tp = (tpp ? *tpp : NULL); |
| 474 | 473 | ||
| 475 | mp = dqp->q_mount; | 474 | dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk; |
| 476 | id = be32_to_cpu(dqp->q_core.d_id); | ||
| 477 | nmaps = 1; | ||
| 478 | newdquot = B_FALSE; | ||
| 479 | 475 | ||
| 480 | /* | 476 | xfs_ilock(quotip, XFS_ILOCK_SHARED); |
| 481 | * If we don't know where the dquot lives, find out. | 477 | if (XFS_IS_THIS_QUOTA_OFF(dqp)) { |
| 482 | */ | ||
| 483 | if (dqp->q_blkno == (xfs_daddr_t) 0) { | ||
| 484 | /* We use the id as an index */ | ||
| 485 | dqp->q_fileoffset = (xfs_fileoff_t)id / | ||
| 486 | mp->m_quotainfo->qi_dqperchunk; | ||
| 487 | nmaps = 1; | ||
| 488 | quotip = XFS_DQ_TO_QIP(dqp); | ||
| 489 | xfs_ilock(quotip, XFS_ILOCK_SHARED); | ||
| 490 | /* | 478 | /* |
| 491 | * Return if this type of quotas is turned off while we didn't | 479 | * Return if this type of quotas is turned off while we |
| 492 | * have an inode lock | 480 | * didn't have the quota inode lock. |
| 493 | */ | 481 | */ |
| 494 | if (XFS_IS_THIS_QUOTA_OFF(dqp)) { | 482 | xfs_iunlock(quotip, XFS_ILOCK_SHARED); |
| 495 | xfs_iunlock(quotip, XFS_ILOCK_SHARED); | 483 | return ESRCH; |
| 496 | return (ESRCH); | 484 | } |
| 497 | } | 485 | |
| 486 | /* | ||
| 487 | * Find the block map; no allocations yet | ||
| 488 | */ | ||
| 489 | error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset, | ||
| 490 | XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, | ||
| 491 | NULL, 0, &map, &nmaps, NULL); | ||
| 492 | |||
| 493 | xfs_iunlock(quotip, XFS_ILOCK_SHARED); | ||
| 494 | if (error) | ||
| 495 | return error; | ||
| 496 | |||
| 497 | ASSERT(nmaps == 1); | ||
| 498 | ASSERT(map.br_blockcount == 1); | ||
| 499 | |||
| 500 | /* | ||
| 501 | * Offset of dquot in the (fixed sized) dquot chunk. | ||
| 502 | */ | ||
| 503 | dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) * | ||
| 504 | sizeof(xfs_dqblk_t); | ||
| 505 | |||
| 506 | ASSERT(map.br_startblock != DELAYSTARTBLOCK); | ||
| 507 | if (map.br_startblock == HOLESTARTBLOCK) { | ||
| 498 | /* | 508 | /* |
| 499 | * Find the block map; no allocations yet | 509 | * We don't allocate unless we're asked to |
| 500 | */ | 510 | */ |
| 501 | error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset, | 511 | if (!(flags & XFS_QMOPT_DQALLOC)) |
| 502 | XFS_DQUOT_CLUSTER_SIZE_FSB, | 512 | return ENOENT; |
| 503 | XFS_BMAPI_METADATA, | ||
| 504 | NULL, 0, &map, &nmaps, NULL); | ||
| 505 | 513 | ||
| 506 | xfs_iunlock(quotip, XFS_ILOCK_SHARED); | 514 | ASSERT(tp); |
| 515 | error = xfs_qm_dqalloc(tpp, mp, dqp, quotip, | ||
| 516 | dqp->q_fileoffset, &bp); | ||
| 507 | if (error) | 517 | if (error) |
| 508 | return (error); | 518 | return error; |
| 509 | ASSERT(nmaps == 1); | 519 | tp = *tpp; |
| 510 | ASSERT(map.br_blockcount == 1); | 520 | } else { |
| 521 | trace_xfs_dqtobp_read(dqp); | ||
| 511 | 522 | ||
| 512 | /* | 523 | /* |
| 513 | * offset of dquot in the (fixed sized) dquot chunk. | 524 | * store the blkno etc so that we don't have to do the |
| 525 | * mapping all the time | ||
| 514 | */ | 526 | */ |
| 515 | dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) * | 527 | dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock); |
| 516 | sizeof(xfs_dqblk_t); | ||
| 517 | if (map.br_startblock == HOLESTARTBLOCK) { | ||
| 518 | /* | ||
| 519 | * We don't allocate unless we're asked to | ||
| 520 | */ | ||
| 521 | if (!(flags & XFS_QMOPT_DQALLOC)) | ||
| 522 | return (ENOENT); | ||
| 523 | |||
| 524 | ASSERT(tp); | ||
| 525 | if ((error = xfs_qm_dqalloc(tpp, mp, dqp, quotip, | ||
| 526 | dqp->q_fileoffset, &bp))) | ||
| 527 | return (error); | ||
| 528 | tp = *tpp; | ||
| 529 | newdquot = B_TRUE; | ||
| 530 | } else { | ||
| 531 | /* | ||
| 532 | * store the blkno etc so that we don't have to do the | ||
| 533 | * mapping all the time | ||
| 534 | */ | ||
| 535 | dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock); | ||
| 536 | } | ||
| 537 | } | ||
| 538 | ASSERT(dqp->q_blkno != DELAYSTARTBLOCK); | ||
| 539 | ASSERT(dqp->q_blkno != HOLESTARTBLOCK); | ||
| 540 | |||
| 541 | /* | ||
| 542 | * Read in the buffer, unless we've just done the allocation | ||
| 543 | * (in which case we already have the buf). | ||
| 544 | */ | ||
| 545 | if (!newdquot) { | ||
| 546 | trace_xfs_dqtobp_read(dqp); | ||
| 547 | 528 | ||
| 548 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, | 529 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, |
| 549 | dqp->q_blkno, | 530 | dqp->q_blkno, |
| @@ -552,13 +533,14 @@ xfs_qm_dqtobp( | |||
| 552 | if (error || !bp) | 533 | if (error || !bp) |
| 553 | return XFS_ERROR(error); | 534 | return XFS_ERROR(error); |
| 554 | } | 535 | } |
| 536 | |||
| 555 | ASSERT(XFS_BUF_ISBUSY(bp)); | 537 | ASSERT(XFS_BUF_ISBUSY(bp)); |
| 556 | ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); | 538 | ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); |
| 557 | 539 | ||
| 558 | /* | 540 | /* |
| 559 | * calculate the location of the dquot inside the buffer. | 541 | * calculate the location of the dquot inside the buffer. |
| 560 | */ | 542 | */ |
| 561 | ddq = (xfs_disk_dquot_t *)((char *)XFS_BUF_PTR(bp) + dqp->q_bufoffset); | 543 | ddq = (struct xfs_disk_dquot *)(XFS_BUF_PTR(bp) + dqp->q_bufoffset); |
| 562 | 544 | ||
| 563 | /* | 545 | /* |
| 564 | * A simple sanity check in case we got a corrupted dquot... | 546 | * A simple sanity check in case we got a corrupted dquot... |
| @@ -1176,18 +1158,18 @@ xfs_qm_dqflush( | |||
| 1176 | xfs_dquot_t *dqp, | 1158 | xfs_dquot_t *dqp, |
| 1177 | uint flags) | 1159 | uint flags) |
| 1178 | { | 1160 | { |
| 1179 | xfs_mount_t *mp; | 1161 | struct xfs_mount *mp = dqp->q_mount; |
| 1180 | xfs_buf_t *bp; | 1162 | struct xfs_buf *bp; |
| 1181 | xfs_disk_dquot_t *ddqp; | 1163 | struct xfs_disk_dquot *ddqp; |
| 1182 | int error; | 1164 | int error; |
| 1183 | 1165 | ||
| 1184 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 1166 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
| 1185 | ASSERT(!completion_done(&dqp->q_flush)); | 1167 | ASSERT(!completion_done(&dqp->q_flush)); |
| 1168 | |||
| 1186 | trace_xfs_dqflush(dqp); | 1169 | trace_xfs_dqflush(dqp); |
| 1187 | 1170 | ||
| 1188 | /* | 1171 | /* |
| 1189 | * If not dirty, or it's pinned and we are not supposed to | 1172 | * If not dirty, or it's pinned and we are not supposed to block, nada. |
| 1190 | * block, nada. | ||
| 1191 | */ | 1173 | */ |
| 1192 | if (!XFS_DQ_IS_DIRTY(dqp) || | 1174 | if (!XFS_DQ_IS_DIRTY(dqp) || |
| 1193 | (!(flags & SYNC_WAIT) && atomic_read(&dqp->q_pincount) > 0)) { | 1175 | (!(flags & SYNC_WAIT) && atomic_read(&dqp->q_pincount) > 0)) { |
| @@ -1201,40 +1183,46 @@ xfs_qm_dqflush( | |||
| 1201 | * down forcibly. If that's the case we must not write this dquot | 1183 | * down forcibly. If that's the case we must not write this dquot |
| 1202 | * to disk, because the log record didn't make it to disk! | 1184 | * to disk, because the log record didn't make it to disk! |
| 1203 | */ | 1185 | */ |
| 1204 | if (XFS_FORCED_SHUTDOWN(dqp->q_mount)) { | 1186 | if (XFS_FORCED_SHUTDOWN(mp)) { |
| 1205 | dqp->dq_flags &= ~(XFS_DQ_DIRTY); | 1187 | dqp->dq_flags &= ~XFS_DQ_DIRTY; |
| 1206 | xfs_dqfunlock(dqp); | 1188 | xfs_dqfunlock(dqp); |
| 1207 | return XFS_ERROR(EIO); | 1189 | return XFS_ERROR(EIO); |
| 1208 | } | 1190 | } |
| 1209 | 1191 | ||
| 1210 | /* | 1192 | /* |
| 1211 | * Get the buffer containing the on-disk dquot | 1193 | * Get the buffer containing the on-disk dquot |
| 1212 | * We don't need a transaction envelope because we know that the | ||
| 1213 | * the ondisk-dquot has already been allocated for. | ||
| 1214 | */ | 1194 | */ |
| 1215 | if ((error = xfs_qm_dqtobp(NULL, dqp, &ddqp, &bp, XFS_QMOPT_DOWARN))) { | 1195 | error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno, |
| 1196 | mp->m_quotainfo->qi_dqchunklen, 0, &bp); | ||
| 1197 | if (error) { | ||
| 1216 | ASSERT(error != ENOENT); | 1198 | ASSERT(error != ENOENT); |
| 1217 | /* | ||
| 1218 | * Quotas could have gotten turned off (ESRCH) | ||
| 1219 | */ | ||
| 1220 | xfs_dqfunlock(dqp); | 1199 | xfs_dqfunlock(dqp); |
| 1221 | return (error); | 1200 | return error; |
| 1222 | } | 1201 | } |
| 1223 | 1202 | ||
| 1224 | if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), | 1203 | /* |
| 1225 | 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) { | 1204 | * Calculate the location of the dquot inside the buffer. |
| 1226 | xfs_force_shutdown(dqp->q_mount, SHUTDOWN_CORRUPT_INCORE); | 1205 | */ |
| 1206 | ddqp = (struct xfs_disk_dquot *)(XFS_BUF_PTR(bp) + dqp->q_bufoffset); | ||
| 1207 | |||
| 1208 | /* | ||
| 1209 | * A simple sanity check in case we got a corrupted dquot.. | ||
| 1210 | */ | ||
| 1211 | if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), 0, | ||
| 1212 | XFS_QMOPT_DOWARN, "dqflush (incore copy)")) { | ||
| 1213 | xfs_buf_relse(bp); | ||
| 1214 | xfs_dqfunlock(dqp); | ||
| 1215 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | ||
| 1227 | return XFS_ERROR(EIO); | 1216 | return XFS_ERROR(EIO); |
| 1228 | } | 1217 | } |
| 1229 | 1218 | ||
| 1230 | /* This is the only portion of data that needs to persist */ | 1219 | /* This is the only portion of data that needs to persist */ |
| 1231 | memcpy(ddqp, &(dqp->q_core), sizeof(xfs_disk_dquot_t)); | 1220 | memcpy(ddqp, &dqp->q_core, sizeof(xfs_disk_dquot_t)); |
| 1232 | 1221 | ||
| 1233 | /* | 1222 | /* |
| 1234 | * Clear the dirty field and remember the flush lsn for later use. | 1223 | * Clear the dirty field and remember the flush lsn for later use. |
| 1235 | */ | 1224 | */ |
| 1236 | dqp->dq_flags &= ~(XFS_DQ_DIRTY); | 1225 | dqp->dq_flags &= ~XFS_DQ_DIRTY; |
| 1237 | mp = dqp->q_mount; | ||
| 1238 | 1226 | ||
| 1239 | xfs_trans_ail_copy_lsn(mp->m_ail, &dqp->q_logitem.qli_flush_lsn, | 1227 | xfs_trans_ail_copy_lsn(mp->m_ail, &dqp->q_logitem.qli_flush_lsn, |
| 1240 | &dqp->q_logitem.qli_item.li_lsn); | 1228 | &dqp->q_logitem.qli_item.li_lsn); |
