diff options
author | Jan Kara <jack@suse.cz> | 2017-08-07 07:19:50 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2017-08-17 16:07:59 -0400 |
commit | 7b9ca4c61bc278b771fb57d6290a31ab1fc7fdac (patch) | |
tree | 3e9c7464525efa2a9dd50d02e7fe8f7df45a4961 /fs/quota | |
parent | f4a8116a4c8c8f754d0ec1498a2ba4b63d114e6a (diff) |
quota: Reduce contention on dq_data_lock
dq_data_lock is currently used to protect all modifications of quota
accounting information, consistency of quota accounting on the inode,
and dquot pointers from inode. As a result contention on the lock can be
pretty heavy.
Reduce the contention on the lock by protecting quota accounting
information by a new dquot->dq_dqb_lock and consistency of quota
accounting with inode usage by inode->i_lock.
This change reduces time to create 500000 files on ext4 on ramdisk by 50
different processes in separate directories by 6% when user quota is
turned on. When those 50 processes belong to 50 different users, the
improvement is about 9%.
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota')
-rw-r--r-- | fs/quota/dquot.c | 287 | ||||
-rw-r--r-- | fs/quota/quota_tree.c | 8 |
2 files changed, 174 insertions, 121 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 411142a2f074..d51797f850c5 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -82,16 +82,19 @@ | |||
82 | #include <linux/uaccess.h> | 82 | #include <linux/uaccess.h> |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * There are three quota SMP locks. dq_list_lock protects all lists with quotas | 85 | * There are five quota SMP locks: |
86 | * and quota formats. | 86 | * * dq_list_lock protects all lists with quotas and quota formats. |
87 | * dq_data_lock protects data from dq_dqb and also mem_dqinfo structures and | 87 | * * dquot->dq_dqb_lock protects data from dq_dqb |
88 | * also guards consistency of dquot->dq_dqb with inode->i_blocks, i_bytes. | 88 | * * inode->i_lock protects inode->i_blocks, i_bytes and also guards |
89 | * i_blocks and i_bytes updates itself are guarded by i_lock acquired directly | 89 | * consistency of dquot->dq_dqb with inode->i_blocks, i_bytes so that |
90 | * in inode_add_bytes() and inode_sub_bytes(). dq_state_lock protects | 90 | * dquot_transfer() can stabilize amount it transfers |
91 | * modifications of quota state (on quotaon and quotaoff) and readers who care | 91 | * * dq_data_lock protects mem_dqinfo structures and modifications of dquot |
92 | * about latest values take it as well. | 92 | * pointers in the inode |
93 | * * dq_state_lock protects modifications of quota state (on quotaon and | ||
94 | * quotaoff) and readers who care about latest values take it as well. | ||
93 | * | 95 | * |
94 | * The spinlock ordering is hence: dq_data_lock > dq_list_lock > i_lock, | 96 | * The spinlock ordering is hence: |
97 | * dq_data_lock > dq_list_lock > i_lock > dquot->dq_dqb_lock, | ||
95 | * dq_list_lock > dq_state_lock | 98 | * dq_list_lock > dq_state_lock |
96 | * | 99 | * |
97 | * Note that some things (eg. sb pointer, type, id) doesn't change during | 100 | * Note that some things (eg. sb pointer, type, id) doesn't change during |
@@ -246,6 +249,7 @@ struct dqstats dqstats; | |||
246 | EXPORT_SYMBOL(dqstats); | 249 | EXPORT_SYMBOL(dqstats); |
247 | 250 | ||
248 | static qsize_t inode_get_rsv_space(struct inode *inode); | 251 | static qsize_t inode_get_rsv_space(struct inode *inode); |
252 | static qsize_t __inode_get_rsv_space(struct inode *inode); | ||
249 | static int __dquot_initialize(struct inode *inode, int type); | 253 | static int __dquot_initialize(struct inode *inode, int type); |
250 | 254 | ||
251 | static inline unsigned int | 255 | static inline unsigned int |
@@ -816,6 +820,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type) | |||
816 | dquot->dq_sb = sb; | 820 | dquot->dq_sb = sb; |
817 | dquot->dq_id = make_kqid_invalid(type); | 821 | dquot->dq_id = make_kqid_invalid(type); |
818 | atomic_set(&dquot->dq_count, 1); | 822 | atomic_set(&dquot->dq_count, 1); |
823 | spin_lock_init(&dquot->dq_dqb_lock); | ||
819 | 824 | ||
820 | return dquot; | 825 | return dquot; |
821 | } | 826 | } |
@@ -1073,21 +1078,6 @@ static void drop_dquot_ref(struct super_block *sb, int type) | |||
1073 | } | 1078 | } |
1074 | } | 1079 | } |
1075 | 1080 | ||
1076 | static inline void dquot_incr_inodes(struct dquot *dquot, qsize_t number) | ||
1077 | { | ||
1078 | dquot->dq_dqb.dqb_curinodes += number; | ||
1079 | } | ||
1080 | |||
1081 | static inline void dquot_incr_space(struct dquot *dquot, qsize_t number) | ||
1082 | { | ||
1083 | dquot->dq_dqb.dqb_curspace += number; | ||
1084 | } | ||
1085 | |||
1086 | static inline void dquot_resv_space(struct dquot *dquot, qsize_t number) | ||
1087 | { | ||
1088 | dquot->dq_dqb.dqb_rsvspace += number; | ||
1089 | } | ||
1090 | |||
1091 | static inline | 1081 | static inline |
1092 | void dquot_free_reserved_space(struct dquot *dquot, qsize_t number) | 1082 | void dquot_free_reserved_space(struct dquot *dquot, qsize_t number) |
1093 | { | 1083 | { |
@@ -1246,21 +1236,24 @@ static int ignore_hardlimit(struct dquot *dquot) | |||
1246 | !(info->dqi_flags & DQF_ROOT_SQUASH)); | 1236 | !(info->dqi_flags & DQF_ROOT_SQUASH)); |
1247 | } | 1237 | } |
1248 | 1238 | ||
1249 | /* needs dq_data_lock */ | 1239 | static int dquot_add_inodes(struct dquot *dquot, qsize_t inodes, |
1250 | static int check_idq(struct dquot *dquot, qsize_t inodes, | 1240 | struct dquot_warn *warn) |
1251 | struct dquot_warn *warn) | ||
1252 | { | 1241 | { |
1253 | qsize_t newinodes = dquot->dq_dqb.dqb_curinodes + inodes; | 1242 | qsize_t newinodes; |
1243 | int ret = 0; | ||
1254 | 1244 | ||
1245 | spin_lock(&dquot->dq_dqb_lock); | ||
1246 | newinodes = dquot->dq_dqb.dqb_curinodes + inodes; | ||
1255 | if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type) || | 1247 | if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type) || |
1256 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) | 1248 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) |
1257 | return 0; | 1249 | goto add; |
1258 | 1250 | ||
1259 | if (dquot->dq_dqb.dqb_ihardlimit && | 1251 | if (dquot->dq_dqb.dqb_ihardlimit && |
1260 | newinodes > dquot->dq_dqb.dqb_ihardlimit && | 1252 | newinodes > dquot->dq_dqb.dqb_ihardlimit && |
1261 | !ignore_hardlimit(dquot)) { | 1253 | !ignore_hardlimit(dquot)) { |
1262 | prepare_warning(warn, dquot, QUOTA_NL_IHARDWARN); | 1254 | prepare_warning(warn, dquot, QUOTA_NL_IHARDWARN); |
1263 | return -EDQUOT; | 1255 | ret = -EDQUOT; |
1256 | goto out; | ||
1264 | } | 1257 | } |
1265 | 1258 | ||
1266 | if (dquot->dq_dqb.dqb_isoftlimit && | 1259 | if (dquot->dq_dqb.dqb_isoftlimit && |
@@ -1269,7 +1262,8 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, | |||
1269 | ktime_get_real_seconds() >= dquot->dq_dqb.dqb_itime && | 1262 | ktime_get_real_seconds() >= dquot->dq_dqb.dqb_itime && |
1270 | !ignore_hardlimit(dquot)) { | 1263 | !ignore_hardlimit(dquot)) { |
1271 | prepare_warning(warn, dquot, QUOTA_NL_ISOFTLONGWARN); | 1264 | prepare_warning(warn, dquot, QUOTA_NL_ISOFTLONGWARN); |
1272 | return -EDQUOT; | 1265 | ret = -EDQUOT; |
1266 | goto out; | ||
1273 | } | 1267 | } |
1274 | 1268 | ||
1275 | if (dquot->dq_dqb.dqb_isoftlimit && | 1269 | if (dquot->dq_dqb.dqb_isoftlimit && |
@@ -1279,30 +1273,40 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, | |||
1279 | dquot->dq_dqb.dqb_itime = ktime_get_real_seconds() + | 1273 | dquot->dq_dqb.dqb_itime = ktime_get_real_seconds() + |
1280 | sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type].dqi_igrace; | 1274 | sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type].dqi_igrace; |
1281 | } | 1275 | } |
1276 | add: | ||
1277 | dquot->dq_dqb.dqb_curinodes = newinodes; | ||
1282 | 1278 | ||
1283 | return 0; | 1279 | out: |
1280 | spin_unlock(&dquot->dq_dqb_lock); | ||
1281 | return ret; | ||
1284 | } | 1282 | } |
1285 | 1283 | ||
1286 | /* needs dq_data_lock */ | 1284 | static int dquot_add_space(struct dquot *dquot, qsize_t space, |
1287 | static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, | 1285 | qsize_t rsv_space, unsigned int flags, |
1288 | struct dquot_warn *warn) | 1286 | struct dquot_warn *warn) |
1289 | { | 1287 | { |
1290 | qsize_t tspace; | 1288 | qsize_t tspace; |
1291 | struct super_block *sb = dquot->dq_sb; | 1289 | struct super_block *sb = dquot->dq_sb; |
1290 | int ret = 0; | ||
1292 | 1291 | ||
1292 | spin_lock(&dquot->dq_dqb_lock); | ||
1293 | if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) || | 1293 | if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) || |
1294 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) | 1294 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) |
1295 | return 0; | 1295 | goto add; |
1296 | 1296 | ||
1297 | tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace | 1297 | tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace |
1298 | + space; | 1298 | + space + rsv_space; |
1299 | |||
1300 | if (flags & DQUOT_SPACE_NOFAIL) | ||
1301 | goto add; | ||
1299 | 1302 | ||
1300 | if (dquot->dq_dqb.dqb_bhardlimit && | 1303 | if (dquot->dq_dqb.dqb_bhardlimit && |
1301 | tspace > dquot->dq_dqb.dqb_bhardlimit && | 1304 | tspace > dquot->dq_dqb.dqb_bhardlimit && |
1302 | !ignore_hardlimit(dquot)) { | 1305 | !ignore_hardlimit(dquot)) { |
1303 | if (!prealloc) | 1306 | if (flags & DQUOT_SPACE_WARN) |
1304 | prepare_warning(warn, dquot, QUOTA_NL_BHARDWARN); | 1307 | prepare_warning(warn, dquot, QUOTA_NL_BHARDWARN); |
1305 | return -EDQUOT; | 1308 | ret = -EDQUOT; |
1309 | goto out; | ||
1306 | } | 1310 | } |
1307 | 1311 | ||
1308 | if (dquot->dq_dqb.dqb_bsoftlimit && | 1312 | if (dquot->dq_dqb.dqb_bsoftlimit && |
@@ -1310,28 +1314,34 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, | |||
1310 | dquot->dq_dqb.dqb_btime && | 1314 | dquot->dq_dqb.dqb_btime && |
1311 | ktime_get_real_seconds() >= dquot->dq_dqb.dqb_btime && | 1315 | ktime_get_real_seconds() >= dquot->dq_dqb.dqb_btime && |
1312 | !ignore_hardlimit(dquot)) { | 1316 | !ignore_hardlimit(dquot)) { |
1313 | if (!prealloc) | 1317 | if (flags & DQUOT_SPACE_WARN) |
1314 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTLONGWARN); | 1318 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTLONGWARN); |
1315 | return -EDQUOT; | 1319 | ret = -EDQUOT; |
1320 | goto out; | ||
1316 | } | 1321 | } |
1317 | 1322 | ||
1318 | if (dquot->dq_dqb.dqb_bsoftlimit && | 1323 | if (dquot->dq_dqb.dqb_bsoftlimit && |
1319 | tspace > dquot->dq_dqb.dqb_bsoftlimit && | 1324 | tspace > dquot->dq_dqb.dqb_bsoftlimit && |
1320 | dquot->dq_dqb.dqb_btime == 0) { | 1325 | dquot->dq_dqb.dqb_btime == 0) { |
1321 | if (!prealloc) { | 1326 | if (flags & DQUOT_SPACE_WARN) { |
1322 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN); | 1327 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN); |
1323 | dquot->dq_dqb.dqb_btime = ktime_get_real_seconds() + | 1328 | dquot->dq_dqb.dqb_btime = ktime_get_real_seconds() + |
1324 | sb_dqopt(sb)->info[dquot->dq_id.type].dqi_bgrace; | 1329 | sb_dqopt(sb)->info[dquot->dq_id.type].dqi_bgrace; |
1325 | } | 1330 | } else { |
1326 | else | ||
1327 | /* | 1331 | /* |
1328 | * We don't allow preallocation to exceed softlimit so exceeding will | 1332 | * We don't allow preallocation to exceed softlimit so exceeding will |
1329 | * be always printed | 1333 | * be always printed |
1330 | */ | 1334 | */ |
1331 | return -EDQUOT; | 1335 | ret = -EDQUOT; |
1336 | goto out; | ||
1337 | } | ||
1332 | } | 1338 | } |
1333 | 1339 | add: | |
1334 | return 0; | 1340 | dquot->dq_dqb.dqb_rsvspace += rsv_space; |
1341 | dquot->dq_dqb.dqb_curspace += space; | ||
1342 | out: | ||
1343 | spin_unlock(&dquot->dq_dqb_lock); | ||
1344 | return ret; | ||
1335 | } | 1345 | } |
1336 | 1346 | ||
1337 | static int info_idq_free(struct dquot *dquot, qsize_t inodes) | 1347 | static int info_idq_free(struct dquot *dquot, qsize_t inodes) |
@@ -1466,8 +1476,15 @@ static int __dquot_initialize(struct inode *inode, int type) | |||
1466 | * did a write before quota was turned on | 1476 | * did a write before quota was turned on |
1467 | */ | 1477 | */ |
1468 | rsv = inode_get_rsv_space(inode); | 1478 | rsv = inode_get_rsv_space(inode); |
1469 | if (unlikely(rsv)) | 1479 | if (unlikely(rsv)) { |
1470 | dquot_resv_space(dquots[cnt], rsv); | 1480 | spin_lock(&inode->i_lock); |
1481 | /* Get reservation again under proper lock */ | ||
1482 | rsv = __inode_get_rsv_space(inode); | ||
1483 | spin_lock(&dquots[cnt]->dq_dqb_lock); | ||
1484 | dquots[cnt]->dq_dqb.dqb_rsvspace += rsv; | ||
1485 | spin_unlock(&dquots[cnt]->dq_dqb_lock); | ||
1486 | spin_unlock(&inode->i_lock); | ||
1487 | } | ||
1471 | } | 1488 | } |
1472 | } | 1489 | } |
1473 | out_lock: | 1490 | out_lock: |
@@ -1562,6 +1579,13 @@ static qsize_t *inode_reserved_space(struct inode * inode) | |||
1562 | return inode->i_sb->dq_op->get_reserved_space(inode); | 1579 | return inode->i_sb->dq_op->get_reserved_space(inode); |
1563 | } | 1580 | } |
1564 | 1581 | ||
1582 | static qsize_t __inode_get_rsv_space(struct inode *inode) | ||
1583 | { | ||
1584 | if (!inode->i_sb->dq_op->get_reserved_space) | ||
1585 | return 0; | ||
1586 | return *inode_reserved_space(inode); | ||
1587 | } | ||
1588 | |||
1565 | static qsize_t inode_get_rsv_space(struct inode *inode) | 1589 | static qsize_t inode_get_rsv_space(struct inode *inode) |
1566 | { | 1590 | { |
1567 | qsize_t ret; | 1591 | qsize_t ret; |
@@ -1569,7 +1593,7 @@ static qsize_t inode_get_rsv_space(struct inode *inode) | |||
1569 | if (!inode->i_sb->dq_op->get_reserved_space) | 1593 | if (!inode->i_sb->dq_op->get_reserved_space) |
1570 | return 0; | 1594 | return 0; |
1571 | spin_lock(&inode->i_lock); | 1595 | spin_lock(&inode->i_lock); |
1572 | ret = *inode_reserved_space(inode); | 1596 | ret = __inode_get_rsv_space(inode); |
1573 | spin_unlock(&inode->i_lock); | 1597 | spin_unlock(&inode->i_lock); |
1574 | return ret; | 1598 | return ret; |
1575 | } | 1599 | } |
@@ -1610,33 +1634,41 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags) | |||
1610 | 1634 | ||
1611 | dquots = i_dquot(inode); | 1635 | dquots = i_dquot(inode); |
1612 | index = srcu_read_lock(&dquot_srcu); | 1636 | index = srcu_read_lock(&dquot_srcu); |
1613 | spin_lock(&dq_data_lock); | 1637 | spin_lock(&inode->i_lock); |
1614 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1638 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1615 | if (!dquots[cnt]) | 1639 | if (!dquots[cnt]) |
1616 | continue; | 1640 | continue; |
1617 | ret = check_bdq(dquots[cnt], number, | 1641 | if (flags & DQUOT_SPACE_RESERVE) { |
1618 | !(flags & DQUOT_SPACE_WARN), &warn[cnt]); | 1642 | ret = dquot_add_space(dquots[cnt], 0, number, flags, |
1619 | if (ret && !(flags & DQUOT_SPACE_NOFAIL)) { | 1643 | &warn[cnt]); |
1620 | spin_unlock(&dq_data_lock); | 1644 | } else { |
1645 | ret = dquot_add_space(dquots[cnt], number, 0, flags, | ||
1646 | &warn[cnt]); | ||
1647 | } | ||
1648 | if (ret) { | ||
1649 | /* Back out changes we already did */ | ||
1650 | for (cnt--; cnt >= 0; cnt--) { | ||
1651 | if (!dquots[cnt]) | ||
1652 | continue; | ||
1653 | spin_lock(&dquots[cnt]->dq_dqb_lock); | ||
1654 | if (flags & DQUOT_SPACE_RESERVE) { | ||
1655 | dquots[cnt]->dq_dqb.dqb_rsvspace -= | ||
1656 | number; | ||
1657 | } else { | ||
1658 | dquots[cnt]->dq_dqb.dqb_curspace -= | ||
1659 | number; | ||
1660 | } | ||
1661 | spin_unlock(&dquots[cnt]->dq_dqb_lock); | ||
1662 | } | ||
1663 | spin_unlock(&inode->i_lock); | ||
1621 | goto out_flush_warn; | 1664 | goto out_flush_warn; |
1622 | } | 1665 | } |
1623 | } | 1666 | } |
1624 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1667 | if (reserve) |
1625 | if (!dquots[cnt]) | ||
1626 | continue; | ||
1627 | if (reserve) | ||
1628 | dquot_resv_space(dquots[cnt], number); | ||
1629 | else | ||
1630 | dquot_incr_space(dquots[cnt], number); | ||
1631 | } | ||
1632 | if (reserve) { | ||
1633 | spin_lock(&inode->i_lock); | ||
1634 | *inode_reserved_space(inode) += number; | 1668 | *inode_reserved_space(inode) += number; |
1635 | spin_unlock(&inode->i_lock); | 1669 | else |
1636 | } else { | 1670 | __inode_add_bytes(inode, number); |
1637 | inode_add_bytes(inode, number); | 1671 | spin_unlock(&inode->i_lock); |
1638 | } | ||
1639 | spin_unlock(&dq_data_lock); | ||
1640 | 1672 | ||
1641 | if (reserve) | 1673 | if (reserve) |
1642 | goto out_flush_warn; | 1674 | goto out_flush_warn; |
@@ -1665,23 +1697,26 @@ int dquot_alloc_inode(struct inode *inode) | |||
1665 | 1697 | ||
1666 | dquots = i_dquot(inode); | 1698 | dquots = i_dquot(inode); |
1667 | index = srcu_read_lock(&dquot_srcu); | 1699 | index = srcu_read_lock(&dquot_srcu); |
1668 | spin_lock(&dq_data_lock); | 1700 | spin_lock(&inode->i_lock); |
1669 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1701 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1670 | if (!dquots[cnt]) | 1702 | if (!dquots[cnt]) |
1671 | continue; | 1703 | continue; |
1672 | ret = check_idq(dquots[cnt], 1, &warn[cnt]); | 1704 | ret = dquot_add_inodes(dquots[cnt], 1, &warn[cnt]); |
1673 | if (ret) | 1705 | if (ret) { |
1706 | for (cnt--; cnt >= 0; cnt--) { | ||
1707 | if (!dquots[cnt]) | ||
1708 | continue; | ||
1709 | /* Back out changes we already did */ | ||
1710 | spin_lock(&dquots[cnt]->dq_dqb_lock); | ||
1711 | dquots[cnt]->dq_dqb.dqb_curinodes--; | ||
1712 | spin_unlock(&dquots[cnt]->dq_dqb_lock); | ||
1713 | } | ||
1674 | goto warn_put_all; | 1714 | goto warn_put_all; |
1675 | } | 1715 | } |
1676 | |||
1677 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | ||
1678 | if (!dquots[cnt]) | ||
1679 | continue; | ||
1680 | dquot_incr_inodes(dquots[cnt], 1); | ||
1681 | } | 1716 | } |
1682 | 1717 | ||
1683 | warn_put_all: | 1718 | warn_put_all: |
1684 | spin_unlock(&dq_data_lock); | 1719 | spin_unlock(&inode->i_lock); |
1685 | if (ret == 0) | 1720 | if (ret == 0) |
1686 | mark_all_dquot_dirty(dquots); | 1721 | mark_all_dquot_dirty(dquots); |
1687 | srcu_read_unlock(&dquot_srcu, index); | 1722 | srcu_read_unlock(&dquot_srcu, index); |
@@ -1708,24 +1743,24 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number) | |||
1708 | 1743 | ||
1709 | dquots = i_dquot(inode); | 1744 | dquots = i_dquot(inode); |
1710 | index = srcu_read_lock(&dquot_srcu); | 1745 | index = srcu_read_lock(&dquot_srcu); |
1711 | spin_lock(&dq_data_lock); | 1746 | spin_lock(&inode->i_lock); |
1712 | /* Claim reserved quotas to allocated quotas */ | 1747 | /* Claim reserved quotas to allocated quotas */ |
1713 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1748 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1714 | if (dquots[cnt]) { | 1749 | if (dquots[cnt]) { |
1715 | struct dquot *dquot = dquots[cnt]; | 1750 | struct dquot *dquot = dquots[cnt]; |
1716 | 1751 | ||
1752 | spin_lock(&dquot->dq_dqb_lock); | ||
1717 | if (WARN_ON_ONCE(dquot->dq_dqb.dqb_rsvspace < number)) | 1753 | if (WARN_ON_ONCE(dquot->dq_dqb.dqb_rsvspace < number)) |
1718 | number = dquot->dq_dqb.dqb_rsvspace; | 1754 | number = dquot->dq_dqb.dqb_rsvspace; |
1719 | dquot->dq_dqb.dqb_curspace += number; | 1755 | dquot->dq_dqb.dqb_curspace += number; |
1720 | dquot->dq_dqb.dqb_rsvspace -= number; | 1756 | dquot->dq_dqb.dqb_rsvspace -= number; |
1757 | spin_unlock(&dquot->dq_dqb_lock); | ||
1721 | } | 1758 | } |
1722 | } | 1759 | } |
1723 | /* Update inode bytes */ | 1760 | /* Update inode bytes */ |
1724 | spin_lock(&inode->i_lock); | ||
1725 | *inode_reserved_space(inode) -= number; | 1761 | *inode_reserved_space(inode) -= number; |
1726 | __inode_add_bytes(inode, number); | 1762 | __inode_add_bytes(inode, number); |
1727 | spin_unlock(&inode->i_lock); | 1763 | spin_unlock(&inode->i_lock); |
1728 | spin_unlock(&dq_data_lock); | ||
1729 | mark_all_dquot_dirty(dquots); | 1764 | mark_all_dquot_dirty(dquots); |
1730 | srcu_read_unlock(&dquot_srcu, index); | 1765 | srcu_read_unlock(&dquot_srcu, index); |
1731 | return 0; | 1766 | return 0; |
@@ -1750,24 +1785,24 @@ void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number) | |||
1750 | 1785 | ||
1751 | dquots = i_dquot(inode); | 1786 | dquots = i_dquot(inode); |
1752 | index = srcu_read_lock(&dquot_srcu); | 1787 | index = srcu_read_lock(&dquot_srcu); |
1753 | spin_lock(&dq_data_lock); | 1788 | spin_lock(&inode->i_lock); |
1754 | /* Claim reserved quotas to allocated quotas */ | 1789 | /* Claim reserved quotas to allocated quotas */ |
1755 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1790 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1756 | if (dquots[cnt]) { | 1791 | if (dquots[cnt]) { |
1757 | struct dquot *dquot = dquots[cnt]; | 1792 | struct dquot *dquot = dquots[cnt]; |
1758 | 1793 | ||
1794 | spin_lock(&dquot->dq_dqb_lock); | ||
1759 | if (WARN_ON_ONCE(dquot->dq_dqb.dqb_curspace < number)) | 1795 | if (WARN_ON_ONCE(dquot->dq_dqb.dqb_curspace < number)) |
1760 | number = dquot->dq_dqb.dqb_curspace; | 1796 | number = dquot->dq_dqb.dqb_curspace; |
1761 | dquot->dq_dqb.dqb_rsvspace += number; | 1797 | dquot->dq_dqb.dqb_rsvspace += number; |
1762 | dquot->dq_dqb.dqb_curspace -= number; | 1798 | dquot->dq_dqb.dqb_curspace -= number; |
1799 | spin_unlock(&dquot->dq_dqb_lock); | ||
1763 | } | 1800 | } |
1764 | } | 1801 | } |
1765 | /* Update inode bytes */ | 1802 | /* Update inode bytes */ |
1766 | spin_lock(&inode->i_lock); | ||
1767 | *inode_reserved_space(inode) += number; | 1803 | *inode_reserved_space(inode) += number; |
1768 | __inode_sub_bytes(inode, number); | 1804 | __inode_sub_bytes(inode, number); |
1769 | spin_unlock(&inode->i_lock); | 1805 | spin_unlock(&inode->i_lock); |
1770 | spin_unlock(&dq_data_lock); | ||
1771 | mark_all_dquot_dirty(dquots); | 1806 | mark_all_dquot_dirty(dquots); |
1772 | srcu_read_unlock(&dquot_srcu, index); | 1807 | srcu_read_unlock(&dquot_srcu, index); |
1773 | return; | 1808 | return; |
@@ -1797,13 +1832,14 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags) | |||
1797 | 1832 | ||
1798 | dquots = i_dquot(inode); | 1833 | dquots = i_dquot(inode); |
1799 | index = srcu_read_lock(&dquot_srcu); | 1834 | index = srcu_read_lock(&dquot_srcu); |
1800 | spin_lock(&dq_data_lock); | 1835 | spin_lock(&inode->i_lock); |
1801 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1836 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1802 | int wtype; | 1837 | int wtype; |
1803 | 1838 | ||
1804 | warn[cnt].w_type = QUOTA_NL_NOWARN; | 1839 | warn[cnt].w_type = QUOTA_NL_NOWARN; |
1805 | if (!dquots[cnt]) | 1840 | if (!dquots[cnt]) |
1806 | continue; | 1841 | continue; |
1842 | spin_lock(&dquots[cnt]->dq_dqb_lock); | ||
1807 | wtype = info_bdq_free(dquots[cnt], number); | 1843 | wtype = info_bdq_free(dquots[cnt], number); |
1808 | if (wtype != QUOTA_NL_NOWARN) | 1844 | if (wtype != QUOTA_NL_NOWARN) |
1809 | prepare_warning(&warn[cnt], dquots[cnt], wtype); | 1845 | prepare_warning(&warn[cnt], dquots[cnt], wtype); |
@@ -1811,15 +1847,13 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags) | |||
1811 | dquot_free_reserved_space(dquots[cnt], number); | 1847 | dquot_free_reserved_space(dquots[cnt], number); |
1812 | else | 1848 | else |
1813 | dquot_decr_space(dquots[cnt], number); | 1849 | dquot_decr_space(dquots[cnt], number); |
1850 | spin_unlock(&dquots[cnt]->dq_dqb_lock); | ||
1814 | } | 1851 | } |
1815 | if (reserve) { | 1852 | if (reserve) |
1816 | spin_lock(&inode->i_lock); | ||
1817 | *inode_reserved_space(inode) -= number; | 1853 | *inode_reserved_space(inode) -= number; |
1818 | spin_unlock(&inode->i_lock); | 1854 | else |
1819 | } else { | 1855 | __inode_sub_bytes(inode, number); |
1820 | inode_sub_bytes(inode, number); | 1856 | spin_unlock(&inode->i_lock); |
1821 | } | ||
1822 | spin_unlock(&dq_data_lock); | ||
1823 | 1857 | ||
1824 | if (reserve) | 1858 | if (reserve) |
1825 | goto out_unlock; | 1859 | goto out_unlock; |
@@ -1845,19 +1879,21 @@ void dquot_free_inode(struct inode *inode) | |||
1845 | 1879 | ||
1846 | dquots = i_dquot(inode); | 1880 | dquots = i_dquot(inode); |
1847 | index = srcu_read_lock(&dquot_srcu); | 1881 | index = srcu_read_lock(&dquot_srcu); |
1848 | spin_lock(&dq_data_lock); | 1882 | spin_lock(&inode->i_lock); |
1849 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1883 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1850 | int wtype; | 1884 | int wtype; |
1851 | 1885 | ||
1852 | warn[cnt].w_type = QUOTA_NL_NOWARN; | 1886 | warn[cnt].w_type = QUOTA_NL_NOWARN; |
1853 | if (!dquots[cnt]) | 1887 | if (!dquots[cnt]) |
1854 | continue; | 1888 | continue; |
1889 | spin_lock(&dquots[cnt]->dq_dqb_lock); | ||
1855 | wtype = info_idq_free(dquots[cnt], 1); | 1890 | wtype = info_idq_free(dquots[cnt], 1); |
1856 | if (wtype != QUOTA_NL_NOWARN) | 1891 | if (wtype != QUOTA_NL_NOWARN) |
1857 | prepare_warning(&warn[cnt], dquots[cnt], wtype); | 1892 | prepare_warning(&warn[cnt], dquots[cnt], wtype); |
1858 | dquot_decr_inodes(dquots[cnt], 1); | 1893 | dquot_decr_inodes(dquots[cnt], 1); |
1894 | spin_unlock(&dquots[cnt]->dq_dqb_lock); | ||
1859 | } | 1895 | } |
1860 | spin_unlock(&dq_data_lock); | 1896 | spin_unlock(&inode->i_lock); |
1861 | mark_all_dquot_dirty(dquots); | 1897 | mark_all_dquot_dirty(dquots); |
1862 | srcu_read_unlock(&dquot_srcu, index); | 1898 | srcu_read_unlock(&dquot_srcu, index); |
1863 | flush_warnings(warn); | 1899 | flush_warnings(warn); |
@@ -1878,7 +1914,7 @@ EXPORT_SYMBOL(dquot_free_inode); | |||
1878 | */ | 1914 | */ |
1879 | int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | 1915 | int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) |
1880 | { | 1916 | { |
1881 | qsize_t space, cur_space; | 1917 | qsize_t cur_space; |
1882 | qsize_t rsv_space = 0; | 1918 | qsize_t rsv_space = 0; |
1883 | qsize_t inode_usage = 1; | 1919 | qsize_t inode_usage = 1; |
1884 | struct dquot *transfer_from[MAXQUOTAS] = {}; | 1920 | struct dquot *transfer_from[MAXQUOTAS] = {}; |
@@ -1905,14 +1941,18 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
1905 | } | 1941 | } |
1906 | 1942 | ||
1907 | spin_lock(&dq_data_lock); | 1943 | spin_lock(&dq_data_lock); |
1944 | spin_lock(&inode->i_lock); | ||
1908 | if (IS_NOQUOTA(inode)) { /* File without quota accounting? */ | 1945 | if (IS_NOQUOTA(inode)) { /* File without quota accounting? */ |
1946 | spin_unlock(&inode->i_lock); | ||
1909 | spin_unlock(&dq_data_lock); | 1947 | spin_unlock(&dq_data_lock); |
1910 | return 0; | 1948 | return 0; |
1911 | } | 1949 | } |
1912 | cur_space = inode_get_bytes(inode); | 1950 | cur_space = __inode_get_bytes(inode); |
1913 | rsv_space = inode_get_rsv_space(inode); | 1951 | rsv_space = __inode_get_rsv_space(inode); |
1914 | space = cur_space + rsv_space; | 1952 | /* |
1915 | /* Build the transfer_from list and check the limits */ | 1953 | * Build the transfer_from list, check limits, and update usage in |
1954 | * the target structures. | ||
1955 | */ | ||
1916 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1956 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1917 | /* | 1957 | /* |
1918 | * Skip changes for same uid or gid or for turned off quota-type. | 1958 | * Skip changes for same uid or gid or for turned off quota-type. |
@@ -1924,28 +1964,33 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
1924 | continue; | 1964 | continue; |
1925 | is_valid[cnt] = 1; | 1965 | is_valid[cnt] = 1; |
1926 | transfer_from[cnt] = i_dquot(inode)[cnt]; | 1966 | transfer_from[cnt] = i_dquot(inode)[cnt]; |
1927 | ret = check_idq(transfer_to[cnt], inode_usage, &warn_to[cnt]); | 1967 | ret = dquot_add_inodes(transfer_to[cnt], inode_usage, |
1968 | &warn_to[cnt]); | ||
1928 | if (ret) | 1969 | if (ret) |
1929 | goto over_quota; | 1970 | goto over_quota; |
1930 | ret = check_bdq(transfer_to[cnt], space, 0, &warn_to[cnt]); | 1971 | ret = dquot_add_space(transfer_to[cnt], cur_space, rsv_space, 0, |
1931 | if (ret) | 1972 | &warn_to[cnt]); |
1973 | if (ret) { | ||
1974 | dquot_decr_inodes(transfer_to[cnt], inode_usage); | ||
1932 | goto over_quota; | 1975 | goto over_quota; |
1976 | } | ||
1933 | } | 1977 | } |
1934 | 1978 | ||
1935 | /* | 1979 | /* Decrease usage for source structures and update quota pointers */ |
1936 | * Finally perform the needed transfer from transfer_from to transfer_to | ||
1937 | */ | ||
1938 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1980 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1939 | if (!is_valid[cnt]) | 1981 | if (!is_valid[cnt]) |
1940 | continue; | 1982 | continue; |
1941 | /* Due to IO error we might not have transfer_from[] structure */ | 1983 | /* Due to IO error we might not have transfer_from[] structure */ |
1942 | if (transfer_from[cnt]) { | 1984 | if (transfer_from[cnt]) { |
1943 | int wtype; | 1985 | int wtype; |
1986 | |||
1987 | spin_lock(&transfer_from[cnt]->dq_dqb_lock); | ||
1944 | wtype = info_idq_free(transfer_from[cnt], inode_usage); | 1988 | wtype = info_idq_free(transfer_from[cnt], inode_usage); |
1945 | if (wtype != QUOTA_NL_NOWARN) | 1989 | if (wtype != QUOTA_NL_NOWARN) |
1946 | prepare_warning(&warn_from_inodes[cnt], | 1990 | prepare_warning(&warn_from_inodes[cnt], |
1947 | transfer_from[cnt], wtype); | 1991 | transfer_from[cnt], wtype); |
1948 | wtype = info_bdq_free(transfer_from[cnt], space); | 1992 | wtype = info_bdq_free(transfer_from[cnt], |
1993 | cur_space + rsv_space); | ||
1949 | if (wtype != QUOTA_NL_NOWARN) | 1994 | if (wtype != QUOTA_NL_NOWARN) |
1950 | prepare_warning(&warn_from_space[cnt], | 1995 | prepare_warning(&warn_from_space[cnt], |
1951 | transfer_from[cnt], wtype); | 1996 | transfer_from[cnt], wtype); |
@@ -1953,14 +1998,11 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
1953 | dquot_decr_space(transfer_from[cnt], cur_space); | 1998 | dquot_decr_space(transfer_from[cnt], cur_space); |
1954 | dquot_free_reserved_space(transfer_from[cnt], | 1999 | dquot_free_reserved_space(transfer_from[cnt], |
1955 | rsv_space); | 2000 | rsv_space); |
2001 | spin_unlock(&transfer_from[cnt]->dq_dqb_lock); | ||
1956 | } | 2002 | } |
1957 | |||
1958 | dquot_incr_inodes(transfer_to[cnt], inode_usage); | ||
1959 | dquot_incr_space(transfer_to[cnt], cur_space); | ||
1960 | dquot_resv_space(transfer_to[cnt], rsv_space); | ||
1961 | |||
1962 | i_dquot(inode)[cnt] = transfer_to[cnt]; | 2003 | i_dquot(inode)[cnt] = transfer_to[cnt]; |
1963 | } | 2004 | } |
2005 | spin_unlock(&inode->i_lock); | ||
1964 | spin_unlock(&dq_data_lock); | 2006 | spin_unlock(&dq_data_lock); |
1965 | 2007 | ||
1966 | mark_all_dquot_dirty(transfer_from); | 2008 | mark_all_dquot_dirty(transfer_from); |
@@ -1974,6 +2016,17 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
1974 | transfer_to[cnt] = transfer_from[cnt]; | 2016 | transfer_to[cnt] = transfer_from[cnt]; |
1975 | return 0; | 2017 | return 0; |
1976 | over_quota: | 2018 | over_quota: |
2019 | /* Back out changes we already did */ | ||
2020 | for (cnt--; cnt >= 0; cnt--) { | ||
2021 | if (!is_valid[cnt]) | ||
2022 | continue; | ||
2023 | spin_lock(&transfer_to[cnt]->dq_dqb_lock); | ||
2024 | dquot_decr_inodes(transfer_to[cnt], inode_usage); | ||
2025 | dquot_decr_space(transfer_to[cnt], cur_space); | ||
2026 | dquot_free_reserved_space(transfer_to[cnt], rsv_space); | ||
2027 | spin_unlock(&transfer_to[cnt]->dq_dqb_lock); | ||
2028 | } | ||
2029 | spin_unlock(&inode->i_lock); | ||
1977 | spin_unlock(&dq_data_lock); | 2030 | spin_unlock(&dq_data_lock); |
1978 | flush_warnings(warn_to); | 2031 | flush_warnings(warn_to); |
1979 | return ret; | 2032 | return ret; |
@@ -2524,7 +2577,7 @@ static void do_get_dqblk(struct dquot *dquot, struct qc_dqblk *di) | |||
2524 | struct mem_dqblk *dm = &dquot->dq_dqb; | 2577 | struct mem_dqblk *dm = &dquot->dq_dqb; |
2525 | 2578 | ||
2526 | memset(di, 0, sizeof(*di)); | 2579 | memset(di, 0, sizeof(*di)); |
2527 | spin_lock(&dq_data_lock); | 2580 | spin_lock(&dquot->dq_dqb_lock); |
2528 | di->d_spc_hardlimit = dm->dqb_bhardlimit; | 2581 | di->d_spc_hardlimit = dm->dqb_bhardlimit; |
2529 | di->d_spc_softlimit = dm->dqb_bsoftlimit; | 2582 | di->d_spc_softlimit = dm->dqb_bsoftlimit; |
2530 | di->d_ino_hardlimit = dm->dqb_ihardlimit; | 2583 | di->d_ino_hardlimit = dm->dqb_ihardlimit; |
@@ -2533,7 +2586,7 @@ static void do_get_dqblk(struct dquot *dquot, struct qc_dqblk *di) | |||
2533 | di->d_ino_count = dm->dqb_curinodes; | 2586 | di->d_ino_count = dm->dqb_curinodes; |
2534 | di->d_spc_timer = dm->dqb_btime; | 2587 | di->d_spc_timer = dm->dqb_btime; |
2535 | di->d_ino_timer = dm->dqb_itime; | 2588 | di->d_ino_timer = dm->dqb_itime; |
2536 | spin_unlock(&dq_data_lock); | 2589 | spin_unlock(&dquot->dq_dqb_lock); |
2537 | } | 2590 | } |
2538 | 2591 | ||
2539 | int dquot_get_dqblk(struct super_block *sb, struct kqid qid, | 2592 | int dquot_get_dqblk(struct super_block *sb, struct kqid qid, |
@@ -2597,7 +2650,7 @@ static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di) | |||
2597 | (di->d_ino_hardlimit > dqi->dqi_max_ino_limit))) | 2650 | (di->d_ino_hardlimit > dqi->dqi_max_ino_limit))) |
2598 | return -ERANGE; | 2651 | return -ERANGE; |
2599 | 2652 | ||
2600 | spin_lock(&dq_data_lock); | 2653 | spin_lock(&dquot->dq_dqb_lock); |
2601 | if (di->d_fieldmask & QC_SPACE) { | 2654 | if (di->d_fieldmask & QC_SPACE) { |
2602 | dm->dqb_curspace = di->d_space - dm->dqb_rsvspace; | 2655 | dm->dqb_curspace = di->d_space - dm->dqb_rsvspace; |
2603 | check_blim = 1; | 2656 | check_blim = 1; |
@@ -2663,7 +2716,7 @@ static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di) | |||
2663 | clear_bit(DQ_FAKE_B, &dquot->dq_flags); | 2716 | clear_bit(DQ_FAKE_B, &dquot->dq_flags); |
2664 | else | 2717 | else |
2665 | set_bit(DQ_FAKE_B, &dquot->dq_flags); | 2718 | set_bit(DQ_FAKE_B, &dquot->dq_flags); |
2666 | spin_unlock(&dq_data_lock); | 2719 | spin_unlock(&dquot->dq_dqb_lock); |
2667 | mark_dquot_dirty(dquot); | 2720 | mark_dquot_dirty(dquot); |
2668 | 2721 | ||
2669 | return 0; | 2722 | return 0; |
diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c index 54f85eb2609c..bb3f59bcfcf5 100644 --- a/fs/quota/quota_tree.c +++ b/fs/quota/quota_tree.c | |||
@@ -389,9 +389,9 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
389 | return ret; | 389 | return ret; |
390 | } | 390 | } |
391 | } | 391 | } |
392 | spin_lock(&dq_data_lock); | 392 | spin_lock(&dquot->dq_dqb_lock); |
393 | info->dqi_ops->mem2disk_dqblk(ddquot, dquot); | 393 | info->dqi_ops->mem2disk_dqblk(ddquot, dquot); |
394 | spin_unlock(&dq_data_lock); | 394 | spin_unlock(&dquot->dq_dqb_lock); |
395 | ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size, | 395 | ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size, |
396 | dquot->dq_off); | 396 | dquot->dq_off); |
397 | if (ret != info->dqi_entry_size) { | 397 | if (ret != info->dqi_entry_size) { |
@@ -649,14 +649,14 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
649 | kfree(ddquot); | 649 | kfree(ddquot); |
650 | goto out; | 650 | goto out; |
651 | } | 651 | } |
652 | spin_lock(&dq_data_lock); | 652 | spin_lock(&dquot->dq_dqb_lock); |
653 | info->dqi_ops->disk2mem_dqblk(dquot, ddquot); | 653 | info->dqi_ops->disk2mem_dqblk(dquot, ddquot); |
654 | if (!dquot->dq_dqb.dqb_bhardlimit && | 654 | if (!dquot->dq_dqb.dqb_bhardlimit && |
655 | !dquot->dq_dqb.dqb_bsoftlimit && | 655 | !dquot->dq_dqb.dqb_bsoftlimit && |
656 | !dquot->dq_dqb.dqb_ihardlimit && | 656 | !dquot->dq_dqb.dqb_ihardlimit && |
657 | !dquot->dq_dqb.dqb_isoftlimit) | 657 | !dquot->dq_dqb.dqb_isoftlimit) |
658 | set_bit(DQ_FAKE_B, &dquot->dq_flags); | 658 | set_bit(DQ_FAKE_B, &dquot->dq_flags); |
659 | spin_unlock(&dq_data_lock); | 659 | spin_unlock(&dquot->dq_dqb_lock); |
660 | kfree(ddquot); | 660 | kfree(ddquot); |
661 | out: | 661 | out: |
662 | dqstats_inc(DQST_READS); | 662 | dqstats_inc(DQST_READS); |