attr.c::notify_change() -- locking_change

From: Craig Christophel (merlin@transgeek.com)
Date: Thu Jan 17 2002 - 18:33:42 EST


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/



This archive was generated by hypermail 2b29 : Wed Jan 23 2002 - 21:00:23 EST