X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Flinux%2Fquotaops.h;h=acc926c64e78941f0dbe74807d287140f128a577;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=9db474dcafd585edf0d92147a5b70ea2a4eaa191;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 9db474dca..acc926c64 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); } }