diff options
author | Jan Kara <jack@suse.cz> | 2010-01-06 11:20:35 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2010-03-04 18:20:19 -0500 |
commit | 26245c949c8473ea7352907b5a54bc34487eb87f (patch) | |
tree | 1b20554c273b42f179f96a8beca9d9314e652847 /fs/quota/dquot.c | |
parent | 3a5b27bf6f29574d667230c7e76e4b83fe3014e0 (diff) |
quota: Cleanup S_NOQUOTA handling
Cleanup handling of S_NOQUOTA inode flag and document it a bit. The flag
does not have to be set under dqptr_sem. Only functions modifying inode's
dquot pointers have to check the flag under dqptr_sem before going forward
with the modification. This way we are sure that we cannot add new dquot
pointers to the inode which is just becoming a quota file.
The good thing about this cleanup is that there are no more places in quota
code which enforce i_mutex vs. dqptr_sem lock ordering (in particular that
dqptr_sem -> i_mutex of quota file). This should silence some (false) lockdep
warnings with ext4 + quota and generally make life of some filesystems easier.
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota/dquot.c')
-rw-r--r-- | fs/quota/dquot.c | 47 |
1 files changed, 11 insertions, 36 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 3fc62b097bed..f6eaf0d8fd6a 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -100,9 +100,13 @@ | |||
100 | * | 100 | * |
101 | * Any operation working on dquots via inode pointers must hold dqptr_sem. If | 101 | * Any operation working on dquots via inode pointers must hold dqptr_sem. If |
102 | * operation is just reading pointers from inode (or not using them at all) the | 102 | * operation is just reading pointers from inode (or not using them at all) the |
103 | * read lock is enough. If pointers are altered function must hold write lock | 103 | * read lock is enough. If pointers are altered function must hold write lock. |
104 | * (these locking rules also apply for S_NOQUOTA flag in the inode - note that | 104 | * Special care needs to be taken about S_NOQUOTA inode flag (marking that |
105 | * for altering the flag i_mutex is also needed). | 105 | * inode is a quota file). Functions adding pointers from inode to dquots have |
106 | * to check this flag under dqptr_sem and then (if S_NOQUOTA is not set) they | ||
107 | * have to do all pointer modifications before dropping dqptr_sem. This makes | ||
108 | * sure they cannot race with quotaon which first sets S_NOQUOTA flag and | ||
109 | * then drops all pointers to dquots from an inode. | ||
106 | * | 110 | * |
107 | * Each dquot has its dq_lock mutex. Locked dquots might not be referenced | 111 | * Each dquot has its dq_lock mutex. Locked dquots might not be referenced |
108 | * from inodes (dquot_alloc_space() and such don't check the dq_lock). | 112 | * from inodes (dquot_alloc_space() and such don't check the dq_lock). |
@@ -1275,7 +1279,6 @@ int dquot_initialize(struct inode *inode, int type) | |||
1275 | } | 1279 | } |
1276 | 1280 | ||
1277 | down_write(&sb_dqopt(sb)->dqptr_sem); | 1281 | down_write(&sb_dqopt(sb)->dqptr_sem); |
1278 | /* Having dqptr_sem we know NOQUOTA flags can't be altered... */ | ||
1279 | if (IS_NOQUOTA(inode)) | 1282 | if (IS_NOQUOTA(inode)) |
1280 | goto out_err; | 1283 | goto out_err; |
1281 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1284 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
@@ -1431,11 +1434,6 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, | |||
1431 | } | 1434 | } |
1432 | 1435 | ||
1433 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1436 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1434 | if (IS_NOQUOTA(inode)) { | ||
1435 | inode_incr_space(inode, number, reserve); | ||
1436 | goto out_unlock; | ||
1437 | } | ||
1438 | |||
1439 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1437 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
1440 | warntype[cnt] = QUOTA_NL_NOWARN; | 1438 | warntype[cnt] = QUOTA_NL_NOWARN; |
1441 | 1439 | ||
@@ -1466,7 +1464,6 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, | |||
1466 | mark_all_dquot_dirty(inode->i_dquot); | 1464 | mark_all_dquot_dirty(inode->i_dquot); |
1467 | out_flush_warn: | 1465 | out_flush_warn: |
1468 | flush_warnings(inode->i_dquot, warntype); | 1466 | flush_warnings(inode->i_dquot, warntype); |
1469 | out_unlock: | ||
1470 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1467 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1471 | out: | 1468 | out: |
1472 | return ret; | 1469 | return ret; |
@@ -1499,10 +1496,6 @@ int dquot_alloc_inode(const struct inode *inode, qsize_t number) | |||
1499 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1496 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
1500 | warntype[cnt] = QUOTA_NL_NOWARN; | 1497 | warntype[cnt] = QUOTA_NL_NOWARN; |
1501 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1498 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1502 | if (IS_NOQUOTA(inode)) { | ||
1503 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1504 | return QUOTA_OK; | ||
1505 | } | ||
1506 | spin_lock(&dq_data_lock); | 1499 | spin_lock(&dq_data_lock); |
1507 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1500 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1508 | if (!inode->i_dquot[cnt]) | 1501 | if (!inode->i_dquot[cnt]) |
@@ -1539,12 +1532,6 @@ int dquot_claim_space(struct inode *inode, qsize_t number) | |||
1539 | } | 1532 | } |
1540 | 1533 | ||
1541 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1534 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1542 | if (IS_NOQUOTA(inode)) { | ||
1543 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1544 | inode_claim_rsv_space(inode, number); | ||
1545 | goto out; | ||
1546 | } | ||
1547 | |||
1548 | spin_lock(&dq_data_lock); | 1535 | spin_lock(&dq_data_lock); |
1549 | /* Claim reserved quotas to allocated quotas */ | 1536 | /* Claim reserved quotas to allocated quotas */ |
1550 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1537 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
@@ -1573,17 +1560,11 @@ int __dquot_free_space(struct inode *inode, qsize_t number, int reserve) | |||
1573 | /* First test before acquiring mutex - solves deadlocks when we | 1560 | /* First test before acquiring mutex - solves deadlocks when we |
1574 | * re-enter the quota code and are already holding the mutex */ | 1561 | * re-enter the quota code and are already holding the mutex */ |
1575 | if (IS_NOQUOTA(inode)) { | 1562 | if (IS_NOQUOTA(inode)) { |
1576 | out_sub: | ||
1577 | inode_decr_space(inode, number, reserve); | 1563 | inode_decr_space(inode, number, reserve); |
1578 | return QUOTA_OK; | 1564 | return QUOTA_OK; |
1579 | } | 1565 | } |
1580 | 1566 | ||
1581 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1567 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1582 | /* Now recheck reliably when holding dqptr_sem */ | ||
1583 | if (IS_NOQUOTA(inode)) { | ||
1584 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1585 | goto out_sub; | ||
1586 | } | ||
1587 | spin_lock(&dq_data_lock); | 1568 | spin_lock(&dq_data_lock); |
1588 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1569 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1589 | if (!inode->i_dquot[cnt]) | 1570 | if (!inode->i_dquot[cnt]) |
@@ -1636,11 +1617,6 @@ int dquot_free_inode(const struct inode *inode, qsize_t number) | |||
1636 | return QUOTA_OK; | 1617 | return QUOTA_OK; |
1637 | 1618 | ||
1638 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1619 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1639 | /* Now recheck reliably when holding dqptr_sem */ | ||
1640 | if (IS_NOQUOTA(inode)) { | ||
1641 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1642 | return QUOTA_OK; | ||
1643 | } | ||
1644 | spin_lock(&dq_data_lock); | 1620 | spin_lock(&dq_data_lock); |
1645 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1621 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1646 | if (!inode->i_dquot[cnt]) | 1622 | if (!inode->i_dquot[cnt]) |
@@ -1692,7 +1668,6 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) | |||
1692 | GRPQUOTA); | 1668 | GRPQUOTA); |
1693 | 1669 | ||
1694 | down_write(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1670 | down_write(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1695 | /* Now recheck reliably when holding dqptr_sem */ | ||
1696 | if (IS_NOQUOTA(inode)) { /* File without quota accounting? */ | 1671 | if (IS_NOQUOTA(inode)) { /* File without quota accounting? */ |
1697 | up_write(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1672 | up_write(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1698 | goto put_all; | 1673 | goto put_all; |
@@ -2010,13 +1985,15 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
2010 | /* We don't want quota and atime on quota files (deadlocks | 1985 | /* We don't want quota and atime on quota files (deadlocks |
2011 | * possible) Also nobody should write to the file - we use | 1986 | * possible) Also nobody should write to the file - we use |
2012 | * special IO operations which ignore the immutable bit. */ | 1987 | * special IO operations which ignore the immutable bit. */ |
2013 | down_write(&dqopt->dqptr_sem); | ||
2014 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); | 1988 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); |
2015 | oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | | 1989 | oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | |
2016 | S_NOQUOTA); | 1990 | S_NOQUOTA); |
2017 | inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; | 1991 | inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; |
2018 | mutex_unlock(&inode->i_mutex); | 1992 | mutex_unlock(&inode->i_mutex); |
2019 | up_write(&dqopt->dqptr_sem); | 1993 | /* |
1994 | * When S_NOQUOTA is set, remove dquot references as no more | ||
1995 | * references can be added | ||
1996 | */ | ||
2020 | sb->dq_op->drop(inode); | 1997 | sb->dq_op->drop(inode); |
2021 | } | 1998 | } |
2022 | 1999 | ||
@@ -2053,14 +2030,12 @@ out_file_init: | |||
2053 | iput(inode); | 2030 | iput(inode); |
2054 | out_lock: | 2031 | out_lock: |
2055 | if (oldflags != -1) { | 2032 | if (oldflags != -1) { |
2056 | down_write(&dqopt->dqptr_sem); | ||
2057 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); | 2033 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); |
2058 | /* Set the flags back (in the case of accidental quotaon() | 2034 | /* Set the flags back (in the case of accidental quotaon() |
2059 | * on a wrong file we don't want to mess up the flags) */ | 2035 | * on a wrong file we don't want to mess up the flags) */ |
2060 | inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE); | 2036 | inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE); |
2061 | inode->i_flags |= oldflags; | 2037 | inode->i_flags |= oldflags; |
2062 | mutex_unlock(&inode->i_mutex); | 2038 | mutex_unlock(&inode->i_mutex); |
2063 | up_write(&dqopt->dqptr_sem); | ||
2064 | } | 2039 | } |
2065 | mutex_unlock(&dqopt->dqonoff_mutex); | 2040 | mutex_unlock(&dqopt->dqonoff_mutex); |
2066 | out_fmt: | 2041 | out_fmt: |