diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 20:32:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 20:32:27 -0400 |
commit | 5fe3a5ae5c09d53b2b3c7a971e1d87ab3a747055 (patch) | |
tree | 1e0d3e10c83e456a1678c4e01acb5ff624129202 /fs/xfs/quota | |
parent | 0fc0531e0a2174377a86fd6953ecaa00287d8f70 (diff) | |
parent | 39dc948c6921169e13224a97fa53188922acfde8 (diff) |
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs: (36 commits)
xfs: semaphore cleanup
xfs: Extend project quotas to support 32bit project ids
xfs: remove xfs_buf wrappers
xfs: remove xfs_cred.h
xfs: remove xfs_globals.h
xfs: remove xfs_version.h
xfs: remove xfs_refcache.h
xfs: fix the xfs_trans_committed
xfs: remove unused t_callback field in struct xfs_trans
xfs: fix bogus m_maxagi check in xfs_iget
xfs: do not use xfs_mod_incore_sb_batch for per-cpu counters
xfs: do not use xfs_mod_incore_sb for per-cpu counters
xfs: remove XFS_MOUNT_NO_PERCPU_SB
xfs: pack xfs_buf structure more tightly
xfs: convert buffer cache hash to rbtree
xfs: serialise inode reclaim within an AG
xfs: batch inode reclaim lookup
xfs: implement batched inode lookups for AG walking
xfs: split out inode walk inode grabbing
xfs: split inode AG walking into separate code for reclaim
...
Diffstat (limited to 'fs/xfs/quota')
-rw-r--r-- | fs/xfs/quota/xfs_dquot.c | 164 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm.c | 221 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm_bhv.c | 2 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm_syscalls.c | 16 |
4 files changed, 149 insertions, 254 deletions
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index e1a2f6800e01..faf8e1a83a12 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); |
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 9a92407109a1..f8e854b4fde8 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -55,8 +55,6 @@ uint ndquot; | |||
55 | kmem_zone_t *qm_dqzone; | 55 | kmem_zone_t *qm_dqzone; |
56 | kmem_zone_t *qm_dqtrxzone; | 56 | kmem_zone_t *qm_dqtrxzone; |
57 | 57 | ||
58 | static cred_t xfs_zerocr; | ||
59 | |||
60 | STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int); | 58 | STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int); |
61 | STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); | 59 | STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); |
62 | 60 | ||
@@ -837,7 +835,7 @@ xfs_qm_dqattach_locked( | |||
837 | xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, | 835 | xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, |
838 | flags & XFS_QMOPT_DQALLOC, | 836 | flags & XFS_QMOPT_DQALLOC, |
839 | ip->i_udquot, &ip->i_gdquot) : | 837 | ip->i_udquot, &ip->i_gdquot) : |
840 | xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ, | 838 | xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ, |
841 | flags & XFS_QMOPT_DQALLOC, | 839 | flags & XFS_QMOPT_DQALLOC, |
842 | ip->i_udquot, &ip->i_gdquot); | 840 | ip->i_udquot, &ip->i_gdquot); |
843 | /* | 841 | /* |
@@ -1199,87 +1197,6 @@ xfs_qm_list_destroy( | |||
1199 | mutex_destroy(&(list->qh_lock)); | 1197 | mutex_destroy(&(list->qh_lock)); |
1200 | } | 1198 | } |
1201 | 1199 | ||
1202 | |||
1203 | /* | ||
1204 | * Stripped down version of dqattach. This doesn't attach, or even look at the | ||
1205 | * dquots attached to the inode. The rationale is that there won't be any | ||
1206 | * attached at the time this is called from quotacheck. | ||
1207 | */ | ||
1208 | STATIC int | ||
1209 | xfs_qm_dqget_noattach( | ||
1210 | xfs_inode_t *ip, | ||
1211 | xfs_dquot_t **O_udqpp, | ||
1212 | xfs_dquot_t **O_gdqpp) | ||
1213 | { | ||
1214 | int error; | ||
1215 | xfs_mount_t *mp; | ||
1216 | xfs_dquot_t *udqp, *gdqp; | ||
1217 | |||
1218 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
1219 | mp = ip->i_mount; | ||
1220 | udqp = NULL; | ||
1221 | gdqp = NULL; | ||
1222 | |||
1223 | if (XFS_IS_UQUOTA_ON(mp)) { | ||
1224 | ASSERT(ip->i_udquot == NULL); | ||
1225 | /* | ||
1226 | * We want the dquot allocated if it doesn't exist. | ||
1227 | */ | ||
1228 | if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_uid, XFS_DQ_USER, | ||
1229 | XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN, | ||
1230 | &udqp))) { | ||
1231 | /* | ||
1232 | * Shouldn't be able to turn off quotas here. | ||
1233 | */ | ||
1234 | ASSERT(error != ESRCH); | ||
1235 | ASSERT(error != ENOENT); | ||
1236 | return error; | ||
1237 | } | ||
1238 | ASSERT(udqp); | ||
1239 | } | ||
1240 | |||
1241 | if (XFS_IS_OQUOTA_ON(mp)) { | ||
1242 | ASSERT(ip->i_gdquot == NULL); | ||
1243 | if (udqp) | ||
1244 | xfs_dqunlock(udqp); | ||
1245 | error = XFS_IS_GQUOTA_ON(mp) ? | ||
1246 | xfs_qm_dqget(mp, ip, | ||
1247 | ip->i_d.di_gid, XFS_DQ_GROUP, | ||
1248 | XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN, | ||
1249 | &gdqp) : | ||
1250 | xfs_qm_dqget(mp, ip, | ||
1251 | ip->i_d.di_projid, XFS_DQ_PROJ, | ||
1252 | XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN, | ||
1253 | &gdqp); | ||
1254 | if (error) { | ||
1255 | if (udqp) | ||
1256 | xfs_qm_dqrele(udqp); | ||
1257 | ASSERT(error != ESRCH); | ||
1258 | ASSERT(error != ENOENT); | ||
1259 | return error; | ||
1260 | } | ||
1261 | ASSERT(gdqp); | ||
1262 | |||
1263 | /* Reacquire the locks in the right order */ | ||
1264 | if (udqp) { | ||
1265 | if (! xfs_qm_dqlock_nowait(udqp)) { | ||
1266 | xfs_dqunlock(gdqp); | ||
1267 | xfs_dqlock(udqp); | ||
1268 | xfs_dqlock(gdqp); | ||
1269 | } | ||
1270 | } | ||
1271 | } | ||
1272 | |||
1273 | *O_udqpp = udqp; | ||
1274 | *O_gdqpp = gdqp; | ||
1275 | |||
1276 | #ifdef QUOTADEBUG | ||
1277 | if (udqp) ASSERT(XFS_DQ_IS_LOCKED(udqp)); | ||
1278 | if (gdqp) ASSERT(XFS_DQ_IS_LOCKED(gdqp)); | ||
1279 | #endif | ||
1280 | return 0; | ||
1281 | } | ||
1282 | |||
1283 | /* | 1200 | /* |
1284 | * Create an inode and return with a reference already taken, but unlocked | 1201 | * Create an inode and return with a reference already taken, but unlocked |
1285 | * This is how we create quota inodes | 1202 | * This is how we create quota inodes |
@@ -1305,8 +1222,8 @@ xfs_qm_qino_alloc( | |||
1305 | return error; | 1222 | return error; |
1306 | } | 1223 | } |
1307 | 1224 | ||
1308 | if ((error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, | 1225 | error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip, &committed); |
1309 | &xfs_zerocr, 0, 1, ip, &committed))) { | 1226 | if (error) { |
1310 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | | 1227 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | |
1311 | XFS_TRANS_ABORT); | 1228 | XFS_TRANS_ABORT); |
1312 | return error; | 1229 | return error; |
@@ -1516,7 +1433,7 @@ xfs_qm_dqiterate( | |||
1516 | rablkcnt = map[i+1].br_blockcount; | 1433 | rablkcnt = map[i+1].br_blockcount; |
1517 | rablkno = map[i+1].br_startblock; | 1434 | rablkno = map[i+1].br_startblock; |
1518 | while (rablkcnt--) { | 1435 | while (rablkcnt--) { |
1519 | xfs_baread(mp->m_ddev_targp, | 1436 | xfs_buf_readahead(mp->m_ddev_targp, |
1520 | XFS_FSB_TO_DADDR(mp, rablkno), | 1437 | XFS_FSB_TO_DADDR(mp, rablkno), |
1521 | mp->m_quotainfo->qi_dqchunklen); | 1438 | mp->m_quotainfo->qi_dqchunklen); |
1522 | rablkno++; | 1439 | rablkno++; |
@@ -1546,18 +1463,34 @@ xfs_qm_dqiterate( | |||
1546 | 1463 | ||
1547 | /* | 1464 | /* |
1548 | * Called by dqusage_adjust in doing a quotacheck. | 1465 | * Called by dqusage_adjust in doing a quotacheck. |
1549 | * Given the inode, and a dquot (either USR or GRP, doesn't matter), | 1466 | * |
1550 | * this updates its incore copy as well as the buffer copy. This is | 1467 | * Given the inode, and a dquot id this updates both the incore dqout as well |
1551 | * so that once the quotacheck is done, we can just log all the buffers, | 1468 | * as the buffer copy. This is so that once the quotacheck is done, we can |
1552 | * as opposed to logging numerous updates to individual dquots. | 1469 | * just log all the buffers, as opposed to logging numerous updates to |
1470 | * individual dquots. | ||
1553 | */ | 1471 | */ |
1554 | STATIC void | 1472 | STATIC int |
1555 | xfs_qm_quotacheck_dqadjust( | 1473 | xfs_qm_quotacheck_dqadjust( |
1556 | xfs_dquot_t *dqp, | 1474 | struct xfs_inode *ip, |
1475 | xfs_dqid_t id, | ||
1476 | uint type, | ||
1557 | xfs_qcnt_t nblks, | 1477 | xfs_qcnt_t nblks, |
1558 | xfs_qcnt_t rtblks) | 1478 | xfs_qcnt_t rtblks) |
1559 | { | 1479 | { |
1560 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 1480 | struct xfs_mount *mp = ip->i_mount; |
1481 | struct xfs_dquot *dqp; | ||
1482 | int error; | ||
1483 | |||
1484 | error = xfs_qm_dqget(mp, ip, id, type, | ||
1485 | XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN, &dqp); | ||
1486 | if (error) { | ||
1487 | /* | ||
1488 | * Shouldn't be able to turn off quotas here. | ||
1489 | */ | ||
1490 | ASSERT(error != ESRCH); | ||
1491 | ASSERT(error != ENOENT); | ||
1492 | return error; | ||
1493 | } | ||
1561 | 1494 | ||
1562 | trace_xfs_dqadjust(dqp); | 1495 | trace_xfs_dqadjust(dqp); |
1563 | 1496 | ||
@@ -1582,11 +1515,13 @@ xfs_qm_quotacheck_dqadjust( | |||
1582 | * There are no timers for the default values set in the root dquot. | 1515 | * There are no timers for the default values set in the root dquot. |
1583 | */ | 1516 | */ |
1584 | if (dqp->q_core.d_id) { | 1517 | if (dqp->q_core.d_id) { |
1585 | xfs_qm_adjust_dqlimits(dqp->q_mount, &dqp->q_core); | 1518 | xfs_qm_adjust_dqlimits(mp, &dqp->q_core); |
1586 | xfs_qm_adjust_dqtimers(dqp->q_mount, &dqp->q_core); | 1519 | xfs_qm_adjust_dqtimers(mp, &dqp->q_core); |
1587 | } | 1520 | } |
1588 | 1521 | ||
1589 | dqp->dq_flags |= XFS_DQ_DIRTY; | 1522 | dqp->dq_flags |= XFS_DQ_DIRTY; |
1523 | xfs_qm_dqput(dqp); | ||
1524 | return 0; | ||
1590 | } | 1525 | } |
1591 | 1526 | ||
1592 | STATIC int | 1527 | STATIC int |
@@ -1629,8 +1564,7 @@ xfs_qm_dqusage_adjust( | |||
1629 | int *res) /* result code value */ | 1564 | int *res) /* result code value */ |
1630 | { | 1565 | { |
1631 | xfs_inode_t *ip; | 1566 | xfs_inode_t *ip; |
1632 | xfs_dquot_t *udqp, *gdqp; | 1567 | xfs_qcnt_t nblks, rtblks = 0; |
1633 | xfs_qcnt_t nblks, rtblks; | ||
1634 | int error; | 1568 | int error; |
1635 | 1569 | ||
1636 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); | 1570 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); |
@@ -1650,51 +1584,24 @@ xfs_qm_dqusage_adjust( | |||
1650 | * the case in all other instances. It's OK that we do this because | 1584 | * the case in all other instances. It's OK that we do this because |
1651 | * quotacheck is done only at mount time. | 1585 | * quotacheck is done only at mount time. |
1652 | */ | 1586 | */ |
1653 | if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip))) { | 1587 | error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip); |
1588 | if (error) { | ||
1654 | *res = BULKSTAT_RV_NOTHING; | 1589 | *res = BULKSTAT_RV_NOTHING; |
1655 | return error; | 1590 | return error; |
1656 | } | 1591 | } |
1657 | 1592 | ||
1658 | /* | 1593 | ASSERT(ip->i_delayed_blks == 0); |
1659 | * Obtain the locked dquots. In case of an error (eg. allocation | ||
1660 | * fails for ENOSPC), we return the negative of the error number | ||
1661 | * to bulkstat, so that it can get propagated to quotacheck() and | ||
1662 | * making us disable quotas for the file system. | ||
1663 | */ | ||
1664 | if ((error = xfs_qm_dqget_noattach(ip, &udqp, &gdqp))) { | ||
1665 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1666 | IRELE(ip); | ||
1667 | *res = BULKSTAT_RV_GIVEUP; | ||
1668 | return error; | ||
1669 | } | ||
1670 | 1594 | ||
1671 | rtblks = 0; | 1595 | if (XFS_IS_REALTIME_INODE(ip)) { |
1672 | if (! XFS_IS_REALTIME_INODE(ip)) { | ||
1673 | nblks = (xfs_qcnt_t)ip->i_d.di_nblocks; | ||
1674 | } else { | ||
1675 | /* | 1596 | /* |
1676 | * Walk thru the extent list and count the realtime blocks. | 1597 | * Walk thru the extent list and count the realtime blocks. |
1677 | */ | 1598 | */ |
1678 | if ((error = xfs_qm_get_rtblks(ip, &rtblks))) { | 1599 | error = xfs_qm_get_rtblks(ip, &rtblks); |
1679 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 1600 | if (error) |
1680 | IRELE(ip); | 1601 | goto error0; |
1681 | if (udqp) | ||
1682 | xfs_qm_dqput(udqp); | ||
1683 | if (gdqp) | ||
1684 | xfs_qm_dqput(gdqp); | ||
1685 | *res = BULKSTAT_RV_GIVEUP; | ||
1686 | return error; | ||
1687 | } | ||
1688 | nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks; | ||
1689 | } | 1602 | } |
1690 | ASSERT(ip->i_delayed_blks == 0); | ||
1691 | 1603 | ||
1692 | /* | 1604 | nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks; |
1693 | * We can't release the inode while holding its dquot locks. | ||
1694 | * The inode can go into inactive and might try to acquire the dquotlocks. | ||
1695 | * So, just unlock here and do a vn_rele at the end. | ||
1696 | */ | ||
1697 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1698 | 1605 | ||
1699 | /* | 1606 | /* |
1700 | * Add the (disk blocks and inode) resources occupied by this | 1607 | * Add the (disk blocks and inode) resources occupied by this |
@@ -1709,26 +1616,36 @@ xfs_qm_dqusage_adjust( | |||
1709 | * and quotaoffs don't race. (Quotachecks happen at mount time only). | 1616 | * and quotaoffs don't race. (Quotachecks happen at mount time only). |
1710 | */ | 1617 | */ |
1711 | if (XFS_IS_UQUOTA_ON(mp)) { | 1618 | if (XFS_IS_UQUOTA_ON(mp)) { |
1712 | ASSERT(udqp); | 1619 | error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_uid, |
1713 | xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks); | 1620 | XFS_DQ_USER, nblks, rtblks); |
1714 | xfs_qm_dqput(udqp); | 1621 | if (error) |
1622 | goto error0; | ||
1715 | } | 1623 | } |
1716 | if (XFS_IS_OQUOTA_ON(mp)) { | 1624 | |
1717 | ASSERT(gdqp); | 1625 | if (XFS_IS_GQUOTA_ON(mp)) { |
1718 | xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks); | 1626 | error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_gid, |
1719 | xfs_qm_dqput(gdqp); | 1627 | XFS_DQ_GROUP, nblks, rtblks); |
1628 | if (error) | ||
1629 | goto error0; | ||
1720 | } | 1630 | } |
1721 | /* | ||
1722 | * Now release the inode. This will send it to 'inactive', and | ||
1723 | * possibly even free blocks. | ||
1724 | */ | ||
1725 | IRELE(ip); | ||
1726 | 1631 | ||
1727 | /* | 1632 | if (XFS_IS_PQUOTA_ON(mp)) { |
1728 | * Goto next inode. | 1633 | error = xfs_qm_quotacheck_dqadjust(ip, xfs_get_projid(ip), |
1729 | */ | 1634 | XFS_DQ_PROJ, nblks, rtblks); |
1635 | if (error) | ||
1636 | goto error0; | ||
1637 | } | ||
1638 | |||
1639 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1640 | IRELE(ip); | ||
1730 | *res = BULKSTAT_RV_DIDONE; | 1641 | *res = BULKSTAT_RV_DIDONE; |
1731 | return 0; | 1642 | return 0; |
1643 | |||
1644 | error0: | ||
1645 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1646 | IRELE(ip); | ||
1647 | *res = BULKSTAT_RV_GIVEUP; | ||
1648 | return error; | ||
1732 | } | 1649 | } |
1733 | 1650 | ||
1734 | /* | 1651 | /* |
@@ -2224,7 +2141,7 @@ xfs_qm_write_sb_changes( | |||
2224 | 2141 | ||
2225 | 2142 | ||
2226 | /* | 2143 | /* |
2227 | * Given an inode, a uid and gid (from cred_t) make sure that we have | 2144 | * Given an inode, a uid, gid and prid make sure that we have |
2228 | * allocated relevant dquot(s) on disk, and that we won't exceed inode | 2145 | * allocated relevant dquot(s) on disk, and that we won't exceed inode |
2229 | * quotas by creating this file. | 2146 | * quotas by creating this file. |
2230 | * This also attaches dquot(s) to the given inode after locking it, | 2147 | * This also attaches dquot(s) to the given inode after locking it, |
@@ -2332,7 +2249,7 @@ xfs_qm_vop_dqalloc( | |||
2332 | xfs_dqunlock(gq); | 2249 | xfs_dqunlock(gq); |
2333 | } | 2250 | } |
2334 | } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { | 2251 | } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { |
2335 | if (ip->i_d.di_projid != prid) { | 2252 | if (xfs_get_projid(ip) != prid) { |
2336 | xfs_iunlock(ip, lockflags); | 2253 | xfs_iunlock(ip, lockflags); |
2337 | if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, | 2254 | if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, |
2338 | XFS_DQ_PROJ, | 2255 | XFS_DQ_PROJ, |
@@ -2454,7 +2371,7 @@ xfs_qm_vop_chown_reserve( | |||
2454 | } | 2371 | } |
2455 | if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { | 2372 | if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { |
2456 | if (XFS_IS_PQUOTA_ON(ip->i_mount) && | 2373 | if (XFS_IS_PQUOTA_ON(ip->i_mount) && |
2457 | ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id)) | 2374 | xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id)) |
2458 | prjflags = XFS_QMOPT_ENOSPC; | 2375 | prjflags = XFS_QMOPT_ENOSPC; |
2459 | 2376 | ||
2460 | if (prjflags || | 2377 | if (prjflags || |
@@ -2558,7 +2475,7 @@ xfs_qm_vop_create_dqattach( | |||
2558 | ip->i_gdquot = gdqp; | 2475 | ip->i_gdquot = gdqp; |
2559 | ASSERT(XFS_IS_OQUOTA_ON(mp)); | 2476 | ASSERT(XFS_IS_OQUOTA_ON(mp)); |
2560 | ASSERT((XFS_IS_GQUOTA_ON(mp) ? | 2477 | ASSERT((XFS_IS_GQUOTA_ON(mp) ? |
2561 | ip->i_d.di_gid : ip->i_d.di_projid) == | 2478 | ip->i_d.di_gid : xfs_get_projid(ip)) == |
2562 | be32_to_cpu(gdqp->q_core.d_id)); | 2479 | be32_to_cpu(gdqp->q_core.d_id)); |
2563 | xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); | 2480 | xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); |
2564 | } | 2481 | } |
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index bea02d786c5d..45b5cb1788ab 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c | |||
@@ -81,7 +81,7 @@ xfs_qm_statvfs( | |||
81 | xfs_mount_t *mp = ip->i_mount; | 81 | xfs_mount_t *mp = ip->i_mount; |
82 | xfs_dquot_t *dqp; | 82 | xfs_dquot_t *dqp; |
83 | 83 | ||
84 | if (!xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) { | 84 | if (!xfs_qm_dqget(mp, NULL, xfs_get_projid(ip), XFS_DQ_PROJ, 0, &dqp)) { |
85 | xfs_fill_statvfs_from_dquot(statp, &dqp->q_core); | 85 | xfs_fill_statvfs_from_dquot(statp, &dqp->q_core); |
86 | xfs_qm_dqput(dqp); | 86 | xfs_qm_dqput(dqp); |
87 | } | 87 | } |
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 45e5849df238..bdebc183223e 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c | |||
@@ -276,7 +276,7 @@ xfs_qm_scall_trunc_qfile( | |||
276 | goto out_unlock; | 276 | goto out_unlock; |
277 | } | 277 | } |
278 | 278 | ||
279 | xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 279 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
280 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | 280 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
281 | 281 | ||
282 | out_unlock: | 282 | out_unlock: |
@@ -875,21 +875,14 @@ xfs_dqrele_inode( | |||
875 | struct xfs_perag *pag, | 875 | struct xfs_perag *pag, |
876 | int flags) | 876 | int flags) |
877 | { | 877 | { |
878 | int error; | ||
879 | |||
880 | /* skip quota inodes */ | 878 | /* skip quota inodes */ |
881 | if (ip == ip->i_mount->m_quotainfo->qi_uquotaip || | 879 | if (ip == ip->i_mount->m_quotainfo->qi_uquotaip || |
882 | ip == ip->i_mount->m_quotainfo->qi_gquotaip) { | 880 | ip == ip->i_mount->m_quotainfo->qi_gquotaip) { |
883 | ASSERT(ip->i_udquot == NULL); | 881 | ASSERT(ip->i_udquot == NULL); |
884 | ASSERT(ip->i_gdquot == NULL); | 882 | ASSERT(ip->i_gdquot == NULL); |
885 | read_unlock(&pag->pag_ici_lock); | ||
886 | return 0; | 883 | return 0; |
887 | } | 884 | } |
888 | 885 | ||
889 | error = xfs_sync_inode_valid(ip, pag); | ||
890 | if (error) | ||
891 | return error; | ||
892 | |||
893 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 886 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
894 | if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) { | 887 | if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) { |
895 | xfs_qm_dqrele(ip->i_udquot); | 888 | xfs_qm_dqrele(ip->i_udquot); |
@@ -900,8 +893,6 @@ xfs_dqrele_inode( | |||
900 | ip->i_gdquot = NULL; | 893 | ip->i_gdquot = NULL; |
901 | } | 894 | } |
902 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 895 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
903 | |||
904 | IRELE(ip); | ||
905 | return 0; | 896 | return 0; |
906 | } | 897 | } |
907 | 898 | ||
@@ -918,8 +909,7 @@ xfs_qm_dqrele_all_inodes( | |||
918 | uint flags) | 909 | uint flags) |
919 | { | 910 | { |
920 | ASSERT(mp->m_quotainfo); | 911 | ASSERT(mp->m_quotainfo); |
921 | xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, | 912 | xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags); |
922 | XFS_ICI_NO_TAG, 0, NULL); | ||
923 | } | 913 | } |
924 | 914 | ||
925 | /*------------------------------------------------------------------------*/ | 915 | /*------------------------------------------------------------------------*/ |
@@ -1175,7 +1165,7 @@ xfs_qm_internalqcheck_adjust( | |||
1175 | } | 1165 | } |
1176 | xfs_qm_internalqcheck_get_dquots(mp, | 1166 | xfs_qm_internalqcheck_get_dquots(mp, |
1177 | (xfs_dqid_t) ip->i_d.di_uid, | 1167 | (xfs_dqid_t) ip->i_d.di_uid, |
1178 | (xfs_dqid_t) ip->i_d.di_projid, | 1168 | (xfs_dqid_t) xfs_get_projid(ip), |
1179 | (xfs_dqid_t) ip->i_d.di_gid, | 1169 | (xfs_dqid_t) ip->i_d.di_gid, |
1180 | &ud, &gd); | 1170 | &ud, &gd); |
1181 | if (XFS_IS_UQUOTA_ON(mp)) { | 1171 | if (XFS_IS_UQUOTA_ON(mp)) { |