diff options
-rw-r--r-- | fs/quota/dquot.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index aad1316a977f..ed14beea8fe3 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -1736,6 +1736,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
1736 | qsize_t rsv_space = 0; | 1736 | qsize_t rsv_space = 0; |
1737 | struct dquot *transfer_from[MAXQUOTAS] = {}; | 1737 | struct dquot *transfer_from[MAXQUOTAS] = {}; |
1738 | int cnt, ret = 0; | 1738 | int cnt, ret = 0; |
1739 | char is_valid[MAXQUOTAS] = {}; | ||
1739 | char warntype_to[MAXQUOTAS]; | 1740 | char warntype_to[MAXQUOTAS]; |
1740 | char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS]; | 1741 | char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS]; |
1741 | 1742 | ||
@@ -1757,8 +1758,15 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
1757 | space = cur_space + rsv_space; | 1758 | space = cur_space + rsv_space; |
1758 | /* Build the transfer_from list and check the limits */ | 1759 | /* Build the transfer_from list and check the limits */ |
1759 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1760 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1761 | /* | ||
1762 | * Skip changes for same uid or gid or for turned off quota-type. | ||
1763 | */ | ||
1760 | if (!transfer_to[cnt]) | 1764 | if (!transfer_to[cnt]) |
1761 | continue; | 1765 | continue; |
1766 | /* Avoid races with quotaoff() */ | ||
1767 | if (!sb_has_quota_active(inode->i_sb, cnt)) | ||
1768 | continue; | ||
1769 | is_valid[cnt] = 1; | ||
1762 | transfer_from[cnt] = inode->i_dquot[cnt]; | 1770 | transfer_from[cnt] = inode->i_dquot[cnt]; |
1763 | ret = check_idq(transfer_to[cnt], 1, warntype_to + cnt); | 1771 | ret = check_idq(transfer_to[cnt], 1, warntype_to + cnt); |
1764 | if (ret) | 1772 | if (ret) |
@@ -1772,12 +1780,8 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
1772 | * Finally perform the needed transfer from transfer_from to transfer_to | 1780 | * Finally perform the needed transfer from transfer_from to transfer_to |
1773 | */ | 1781 | */ |
1774 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1782 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1775 | /* | 1783 | if (!is_valid[cnt]) |
1776 | * Skip changes for same uid or gid or for turned off quota-type. | ||
1777 | */ | ||
1778 | if (!transfer_to[cnt]) | ||
1779 | continue; | 1784 | continue; |
1780 | |||
1781 | /* Due to IO error we might not have transfer_from[] structure */ | 1785 | /* Due to IO error we might not have transfer_from[] structure */ |
1782 | if (transfer_from[cnt]) { | 1786 | if (transfer_from[cnt]) { |
1783 | warntype_from_inodes[cnt] = | 1787 | warntype_from_inodes[cnt] = |
@@ -1803,7 +1807,9 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
1803 | mark_all_dquot_dirty(transfer_to); | 1807 | mark_all_dquot_dirty(transfer_to); |
1804 | /* Pass back references to put */ | 1808 | /* Pass back references to put */ |
1805 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1809 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
1806 | transfer_to[cnt] = transfer_from[cnt]; | 1810 | if (is_valid[cnt]) |
1811 | transfer_to[cnt] = transfer_from[cnt]; | ||
1812 | |||
1807 | warn: | 1813 | warn: |
1808 | flush_warnings(transfer_to, warntype_to); | 1814 | flush_warnings(transfer_to, warntype_to); |
1809 | flush_warnings(transfer_from, warntype_from_inodes); | 1815 | flush_warnings(transfer_from, warntype_from_inodes); |