lkml.org 
[lkml]   [2002]   [Jan]   [17]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
FromCraig Christophel <>
Subjectattr.c::notify_change() -- locking_change
DateThu, 17 Jan 2002 18:33:42 -0500
ok this is a first attempt at changing notify_change().....
please look at the following code for any obvious issues.  especially the 
wait_on_inode functions.  I am not sure if a new specific wait_on_attr_inode 
should be created or if this change is OK.  I am trying to remove the BKL (-- 
so any "please review all filesystems" comments are unneeded as I know this.) 
from the VFS layer and this is just one small portion of that effort. 

Craig

Index: linux/fs//attr.c
===================================================================
RCS file: /home/Media/cvs/linux/fs/attr.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 attr.c
--- linux/fs//attr.c	16 Jan 2002 18:26:33 -0000	1.1.1.1
+++ linux/fs//attr.c	17 Jan 2002 23:30:14 -0000
@@ -111,10 +111,13 @@
 	return dn_mask;
 }
 
+/* inode_lock is needed to protect i_state */
+
+extern spinlock_t inode_lock;
 int notify_change(struct dentry * dentry, struct iattr * attr)
 {
 	struct inode *inode = dentry->d_inode;
-	int error;
+	int error,tflag;
 	time_t now = CURRENT_TIME;
 	unsigned int ia_valid = attr->ia_valid;
 
@@ -127,7 +130,25 @@
 	if (!(ia_valid & ATTR_MTIME_SET))
 		attr->ia_mtime = now;
 
-	lock_kernel();
+	/*
+	 * The special i_state flag I_ATTR_LOCK protects
+	 * the following code block  this is for serialization
+	 * purposes previously managed by lock_kernel();
+	 */
+
+	do {
+		wait_on_inode(inode,I_ATTR_LOCK);
+		spin_lock(&inode_lock);
+		if(inode->i_state & I_ATTR_LOCK) {
+			spin_unlock(&inode_lock);
+		}
+		else {
+			inode->i_state =| I_ATTR_LOCK;
+			tflag = 1;
+			spin_unlock(&inode_lock);
+		}
+	} while(!tflag);
+
 	if (inode->i_op && inode->i_op->setattr) 
 		error = inode->i_op->setattr(dentry, attr);
 	else {
@@ -140,7 +161,9 @@
 				error = inode_setattr(inode, attr);
 		}
 	}
-	unlock_kernel();
+	spin_lock(&inode_lock);
+	inode->i_state =& ~I_ATTR_LOCK;
+	spin_unlock(&inode_lock);
 	if (!error) {
 		unsigned long dn_mask = setattr_mask(ia_valid);
 		if (dn_mask)
Index: linux/fs//inode.c
===================================================================
RCS file: /home/Media/cvs/linux/fs/inode.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 inode.c
--- linux/fs//inode.c	16 Jan 2002 18:26:32 -0000	1.1.1.1
+++ linux/fs//inode.c	17 Jan 2002 23:01:57 -0000
@@ -163,14 +163,14 @@
 	spin_unlock(&inode_lock);
 }
 
-static void __wait_on_inode(struct inode * inode)
+static void __wait_on_inode(struct inode * inode,int flag)
 {
 	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue(&inode->i_wait, &wait);
 repeat:
 	set_current_state(TASK_UNINTERRUPTIBLE);
-	if (inode->i_state & I_LOCK) {
+	if (inode->i_state & flag) {
 		schedule();
 		goto repeat;
 	}
@@ -178,13 +178,6 @@
 	current->state = TASK_RUNNING;
 }
 
-static inline void wait_on_inode(struct inode *inode)
-{
-	if (inode->i_state & I_LOCK)
-		__wait_on_inode(inode);
-}
-
-
 static inline void write_inode(struct inode *inode, int sync)
 {
 	if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->write_inode && 
!is_bad_inode(inode))
@@ -250,7 +243,7 @@
 	if (inode->i_state & I_LOCK) {
 		__iget(inode);
 		spin_unlock(&inode_lock);
-		__wait_on_inode(inode);
+		__wait_on_inode(inode,I_LOCK);
 		iput(inode);
 		spin_lock(&inode_lock);
 	} else {
@@ -273,7 +266,7 @@
 		struct inode *inode = list_entry(tmp, struct inode, i_list);
 		__iget(inode);
 		spin_unlock(&inode_lock);
-		__wait_on_inode(inode);
+		__wait_on_inode(inode,I_LOCK);
 		iput(inode);
 		spin_lock(&inode_lock);
 	}
@@ -435,7 +428,7 @@
 			sync_one(inode, sync);
 		spin_unlock(&inode_lock);
 		if (sync)
-			wait_on_inode(inode);
+			wait_on_inode(inode,I_LOCK);
 	}
 	else
 		printk(KERN_ERR "write_inode_now: no super block\n");
@@ -491,7 +484,7 @@
 	if (need_write_inode_now)
 		write_inode_now(inode, 1);
 	else
-		wait_on_inode(inode);
+		wait_on_inode(inode,I_LOCK);
 
 	return err;
 }
@@ -515,7 +508,7 @@
 		BUG();
 	if (inode->i_state & I_CLEAR)
 		BUG();
-	wait_on_inode(inode);
+	wait_on_inode(inode,I_LOCK);
 	DQUOT_DROP(inode);
 	if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->clear_inode)
 		inode->i_sb->s_op->clear_inode(inode);
@@ -904,7 +897,7 @@
 		spin_unlock(&inode_lock);
 		destroy_inode(inode);
 		inode = old;
-		wait_on_inode(inode);
+		wait_on_inode(inode,I_LOCK);
 	}
 	return inode;
 }
@@ -982,7 +975,7 @@
 	if (inode) {
 		__iget(inode);
 		spin_unlock(&inode_lock);
-		wait_on_inode(inode);
+		wait_on_inode(inode,I_LOCK);
 		return inode;
 	}
 	spin_unlock(&inode_lock);
Index: linux/include/linux//fs.h
===================================================================
RCS file: /home/Media/cvs/linux/include/linux/fs.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 fs.h
--- linux/include/linux//fs.h	16 Jan 2002 18:28:27 -0000	1.1.1.1
+++ linux/include/linux//fs.h	17 Jan 2002 22:45:23 -0000
@@ -915,9 +915,15 @@
 #define I_LOCK			8
 #define I_FREEING		16
 #define I_CLEAR			32
+#define I_ADDR_LOCK		64
 
 #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
-
+extern void __wait_on_inode(struct inode *,int);
+static inline void wait_on_inode(struct inode *inode, int flag);
+{
+	if (inode->i_state & flag)
+		__wait_on_inode(inode,flag);
+}
 extern void __mark_inode_dirty(struct inode *, int);
 static inline void mark_inode_dirty(struct inode *inode)
 {
-
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 12:15    [W:0.192 / U:0.110 seconds]
©2003-2008 Jasper Spaans