From ad816f4a1c9420257060c9282dbf7a10b7ccdf88 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sat, 9 Oct 2010 23:15:30 +0400 Subject: [PATCH] --- yaml --- r: 218832 b: refs/heads/master c: 9e32784b71c2c84895016ca6ab271591669c02aa h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/quota/dquot.c | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index cbb5c3eca177..d7b3f69f284f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a910eefa511f9d1118effc13fba6773163502c4f +refs/heads/master: 9e32784b71c2c84895016ca6ab271591669c02aa diff --git a/trunk/fs/quota/dquot.c b/trunk/fs/quota/dquot.c index aad1316a977f..ed14beea8fe3 100644 --- a/trunk/fs/quota/dquot.c +++ b/trunk/fs/quota/dquot.c @@ -1736,6 +1736,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) qsize_t rsv_space = 0; struct dquot *transfer_from[MAXQUOTAS] = {}; int cnt, ret = 0; + char is_valid[MAXQUOTAS] = {}; char warntype_to[MAXQUOTAS]; char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS]; @@ -1757,8 +1758,15 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) space = cur_space + rsv_space; /* Build the transfer_from list and check the limits */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { + /* + * Skip changes for same uid or gid or for turned off quota-type. + */ if (!transfer_to[cnt]) continue; + /* Avoid races with quotaoff() */ + if (!sb_has_quota_active(inode->i_sb, cnt)) + continue; + is_valid[cnt] = 1; transfer_from[cnt] = inode->i_dquot[cnt]; ret = check_idq(transfer_to[cnt], 1, warntype_to + cnt); if (ret) @@ -1772,12 +1780,8 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) * Finally perform the needed transfer from transfer_from to transfer_to */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - /* - * Skip changes for same uid or gid or for turned off quota-type. - */ - if (!transfer_to[cnt]) + if (!is_valid[cnt]) continue; - /* Due to IO error we might not have transfer_from[] structure */ if (transfer_from[cnt]) { warntype_from_inodes[cnt] = @@ -1803,7 +1807,9 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) mark_all_dquot_dirty(transfer_to); /* Pass back references to put */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) - transfer_to[cnt] = transfer_from[cnt]; + if (is_valid[cnt]) + transfer_to[cnt] = transfer_from[cnt]; + warn: flush_warnings(transfer_to, warntype_to); flush_warnings(transfer_from, warntype_from_inodes);