lkml.org 
[lkml]   [2003]   [Oct]   [15]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateWed, 15 Oct 2003 13:06:47 +0200
FromJan Kara <>
Subject[PATCH] Quota locking fix
  Hi Linus,

  attached patch should fix 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 is attached.
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:49    [from the cache]
©2003-2008