lkml.org 
[lkml]   [2003]   [Oct]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] Quota locking fix
  Hi Linus,

I'm resending patch which fixes a quota locking problem causing deadlock
(when inode was being released from icache and it caused newly created
quota structure to be written). The patch against 2.6.0-test7 and should
apply at test8 too. Please apply.

Honza

------------- cut here ---------------

diff -ruNX /home/jack/.kerndiffexclude linux-2.6.0-test7/fs/dquot.c linux-2.6.0-test7-1-lockfix/fs/dquot.c
--- linux-2.6.0-test7/fs/dquot.c Tue Oct 14 15:52:08 2003
+++ linux-2.6.0-test7-1-lockfix/fs/dquot.c Tue Oct 14 16:26:28 2003
@@ -826,28 +826,49 @@
}

/*
- * Release all quota for the specified inode.
- *
- * Note: this is a blocking operation.
+ * Remove references to quota from inode
+ * This function needs dqptr_sem for writing
*/
-static void dquot_drop_nolock(struct inode *inode)
+static void dquot_drop_iupdate(struct inode *inode, struct dquot **to_drop)
{
int cnt;

inode->i_flags &= ~S_QUOTA;
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt] == NODQUOT)
- continue;
- dqput(inode->i_dquot[cnt]);
+ to_drop[cnt] = inode->i_dquot[cnt];
inode->i_dquot[cnt] = NODQUOT;
}
}

+/*
+ * Release all quotas referenced by inode
+ */
void dquot_drop(struct inode *inode)
{
+ struct dquot *to_drop[MAXQUOTAS];
+ int cnt;
+
down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
- dquot_drop_nolock(inode);
+ dquot_drop_iupdate(inode, to_drop);
up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ if (to_drop[cnt] != NODQUOT)
+ dqput(to_drop[cnt]);
+}
+
+/*
+ * Release all quotas referenced by inode.
+ * This function assumes dqptr_sem for writing
+ */
+void dquot_drop_nolock(struct inode *inode)
+{
+ struct dquot *to_drop[MAXQUOTAS];
+ int cnt;
+
+ dquot_drop_iupdate(inode, to_drop);
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ if (to_drop[cnt] != NODQUOT)
+ dqput(to_drop[cnt]);
}

/*
@@ -862,6 +883,10 @@
warntype[cnt] = NOWARN;

down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ if (IS_NOQUOTA(inode)) {
+ up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ return QUOTA_OK;
+ }
spin_lock(&dq_data_lock);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (inode->i_dquot[cnt] == NODQUOT)
@@ -894,6 +919,10 @@
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
warntype[cnt] = NOWARN;
down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ if (IS_NOQUOTA(inode)) {
+ up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ return QUOTA_OK;
+ }
spin_lock(&dq_data_lock);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (inode->i_dquot[cnt] == NODQUOT)
@@ -923,6 +952,10 @@
unsigned int cnt;

down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ if (IS_NOQUOTA(inode)) {
+ up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ return;
+ }
spin_lock(&dq_data_lock);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (inode->i_dquot[cnt] == NODQUOT)
@@ -942,6 +975,10 @@
unsigned int cnt;

down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ if (IS_NOQUOTA(inode)) {
+ up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ return;
+ }
spin_lock(&dq_data_lock);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (inode->i_dquot[cnt] == NODQUOT)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 13:58    [W:0.042 / U:0.112 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site