diff options
| author | Jan Kara <jack@ucw.cz> | 2004-07-10 19:28:28 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-07-10 19:28:28 -0700 |
| commit | 7f0fdc5d3f99a3e4fa6d486bd89243456bcb3e3d (patch) | |
| tree | 9048290c4c17e0d9fbbb0b47c0b4269a42c1091a /include/linux/quotaops.h | |
| parent | 97e5cc051adc3e87e32fba7ea513c41cb69f5f43 (diff) | |
[PATCH] quota: inode->i_flags locking fixes
The patch fixes locking of i_flags. It removes S_QUOTA flag from i_flags
because it was almost unused and updating it on some places correctly
(under i_sem) would be tricky. Note that accessing of S_NOQUOTA flag is
serialized by dqptr_sem and so we can reliably tested without i_sem.
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux/quotaops.h')
| -rw-r--r-- | include/linux/quotaops.h | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 9db474dcafd5..acc926c64e78 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -69,9 +69,22 @@ static __inline__ void DQUOT_INIT(struct inode *inode) /* The same as with DQUOT_INIT */ static __inline__ void DQUOT_DROP(struct inode *inode) { - if (IS_QUOTAINIT(inode)) { - BUG_ON(!inode->i_sb); - inode->i_sb->dq_op->drop(inode); /* Ops must be set when there's any quota... */ + /* Here we can get arbitrary inode from clear_inode() so we have + * to be careful. OTOH we don't need locking as quota operations + * are allowed to change only at mount time */ + if (!IS_NOQUOTA(inode) && inode->i_sb && inode->i_sb->dq_op + && inode->i_sb->dq_op->drop) { + int cnt; + /* Test before calling to rule out calls from proc and such + * where we are not allowed to block. Note that this is + * actually reliable test even without the lock - the caller + * must assure that nobody can come after the DQUOT_DROP and + * add quota pointers back anyway */ + for (cnt = 0; cnt < MAXQUOTAS; cnt++) + if (inode->i_dquot[cnt] != NODQUOT) + break; + if (cnt < MAXQUOTAS) + inode->i_sb->dq_op->drop(inode); } } |
