[PATCH v2 3/7] fsnotify: Simplify inode iteration on umount

2016-07-11 Thread Waiman Long
From: Jan Kara 

fsnotify_unmount_inodes() played complex tricks to pin next inode in the
sb->s_inodes list when iterating over all inodes. If we switch to
keeping current inode pinned somewhat longer, we can make the code much
simpler and standard.

Signed-off-by: Jan Kara 
Signed-off-by: Waiman Long 
---
 fs/notify/inode_mark.c |   45 +
 1 files changed, 9 insertions(+), 36 deletions(-)

diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index 741077d..a364524 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -150,12 +150,10 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
  */
 void fsnotify_unmount_inodes(struct super_block *sb)
 {
-   struct inode *inode, *next_i, *need_iput = NULL;
+   struct inode *inode, *iput_inode = NULL;
 
spin_lock(>s_inode_list_lock);
-   list_for_each_entry_safe(inode, next_i, >s_inodes, i_sb_list) {
-   struct inode *need_iput_tmp;
-
+   list_for_each_entry(inode, >s_inodes, i_sb_list) {
/*
 * We cannot __iget() an inode in state I_FREEING,
 * I_WILL_FREE, or I_NEW which is fine because by that point
@@ -178,49 +176,24 @@ void fsnotify_unmount_inodes(struct super_block *sb)
continue;
}
 
-   need_iput_tmp = need_iput;
-   need_iput = NULL;
-
-   /* In case fsnotify_inode_delete() drops a reference. */
-   if (inode != need_iput_tmp)
-   __iget(inode);
-   else
-   need_iput_tmp = NULL;
+   __iget(inode);
spin_unlock(>i_lock);
-
-   /* In case the dropping of a reference would nuke next_i. */
-   while (_i->i_sb_list != >s_inodes) {
-   spin_lock(_i->i_lock);
-   if (!(next_i->i_state & (I_FREEING | I_WILL_FREE)) &&
-   atomic_read(_i->i_count)) {
-   __iget(next_i);
-   need_iput = next_i;
-   spin_unlock(_i->i_lock);
-   break;
-   }
-   spin_unlock(_i->i_lock);
-   next_i = list_next_entry(next_i, i_sb_list);
-   }
-
-   /*
-* We can safely drop s_inode_list_lock here because either
-* we actually hold references on both inode and next_i or
-* end of list.  Also no new inodes will be added since the
-* umount has begun.
-*/
spin_unlock(>s_inode_list_lock);
 
-   if (need_iput_tmp)
-   iput(need_iput_tmp);
+   if (iput_inode)
+   iput(iput_inode);
 
/* for each watch, send FS_UNMOUNT and then remove it */
fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 
0);
 
fsnotify_inode_delete(inode);
 
-   iput(inode);
+   iput_inode = inode;
 
spin_lock(>s_inode_list_lock);
}
spin_unlock(>s_inode_list_lock);
+
+   if (iput_inode)
+   iput(iput_inode);
 }
-- 
1.7.1



[PATCH v2 3/7] fsnotify: Simplify inode iteration on umount

2016-07-11 Thread Waiman Long
From: Jan Kara 

fsnotify_unmount_inodes() played complex tricks to pin next inode in the
sb->s_inodes list when iterating over all inodes. If we switch to
keeping current inode pinned somewhat longer, we can make the code much
simpler and standard.

Signed-off-by: Jan Kara 
Signed-off-by: Waiman Long 
---
 fs/notify/inode_mark.c |   45 +
 1 files changed, 9 insertions(+), 36 deletions(-)

diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index 741077d..a364524 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -150,12 +150,10 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
  */
 void fsnotify_unmount_inodes(struct super_block *sb)
 {
-   struct inode *inode, *next_i, *need_iput = NULL;
+   struct inode *inode, *iput_inode = NULL;
 
spin_lock(>s_inode_list_lock);
-   list_for_each_entry_safe(inode, next_i, >s_inodes, i_sb_list) {
-   struct inode *need_iput_tmp;
-
+   list_for_each_entry(inode, >s_inodes, i_sb_list) {
/*
 * We cannot __iget() an inode in state I_FREEING,
 * I_WILL_FREE, or I_NEW which is fine because by that point
@@ -178,49 +176,24 @@ void fsnotify_unmount_inodes(struct super_block *sb)
continue;
}
 
-   need_iput_tmp = need_iput;
-   need_iput = NULL;
-
-   /* In case fsnotify_inode_delete() drops a reference. */
-   if (inode != need_iput_tmp)
-   __iget(inode);
-   else
-   need_iput_tmp = NULL;
+   __iget(inode);
spin_unlock(>i_lock);
-
-   /* In case the dropping of a reference would nuke next_i. */
-   while (_i->i_sb_list != >s_inodes) {
-   spin_lock(_i->i_lock);
-   if (!(next_i->i_state & (I_FREEING | I_WILL_FREE)) &&
-   atomic_read(_i->i_count)) {
-   __iget(next_i);
-   need_iput = next_i;
-   spin_unlock(_i->i_lock);
-   break;
-   }
-   spin_unlock(_i->i_lock);
-   next_i = list_next_entry(next_i, i_sb_list);
-   }
-
-   /*
-* We can safely drop s_inode_list_lock here because either
-* we actually hold references on both inode and next_i or
-* end of list.  Also no new inodes will be added since the
-* umount has begun.
-*/
spin_unlock(>s_inode_list_lock);
 
-   if (need_iput_tmp)
-   iput(need_iput_tmp);
+   if (iput_inode)
+   iput(iput_inode);
 
/* for each watch, send FS_UNMOUNT and then remove it */
fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 
0);
 
fsnotify_inode_delete(inode);
 
-   iput(inode);
+   iput_inode = inode;
 
spin_lock(>s_inode_list_lock);
}
spin_unlock(>s_inode_list_lock);
+
+   if (iput_inode)
+   iput(iput_inode);
 }
-- 
1.7.1