Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro: "Eric's s_inodes softlockup fixes + Jan's fix for recent regression from pipe rework" * 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fs: call fsnotify_sb_delete after evict_inodes fs: avoid softlockups in s_inodes iterators pipe: Fix bogus dereference in iov_iter_alignment()
This commit is contained in:
commit
9efa3ed504
|
@ -35,11 +35,11 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
spin_unlock(&sb->s_inode_list_lock);
|
spin_unlock(&sb->s_inode_list_lock);
|
||||||
|
|
||||||
cond_resched();
|
|
||||||
invalidate_mapping_pages(inode->i_mapping, 0, -1);
|
invalidate_mapping_pages(inode->i_mapping, 0, -1);
|
||||||
iput(toput_inode);
|
iput(toput_inode);
|
||||||
toput_inode = inode;
|
toput_inode = inode;
|
||||||
|
|
||||||
|
cond_resched();
|
||||||
spin_lock(&sb->s_inode_list_lock);
|
spin_lock(&sb->s_inode_list_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&sb->s_inode_list_lock);
|
spin_unlock(&sb->s_inode_list_lock);
|
||||||
|
|
|
@ -676,6 +676,7 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty)
|
||||||
struct inode *inode, *next;
|
struct inode *inode, *next;
|
||||||
LIST_HEAD(dispose);
|
LIST_HEAD(dispose);
|
||||||
|
|
||||||
|
again:
|
||||||
spin_lock(&sb->s_inode_list_lock);
|
spin_lock(&sb->s_inode_list_lock);
|
||||||
list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) {
|
list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) {
|
||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
|
@ -698,6 +699,12 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty)
|
||||||
inode_lru_list_del(inode);
|
inode_lru_list_del(inode);
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
list_add(&inode->i_lru, &dispose);
|
list_add(&inode->i_lru, &dispose);
|
||||||
|
if (need_resched()) {
|
||||||
|
spin_unlock(&sb->s_inode_list_lock);
|
||||||
|
cond_resched();
|
||||||
|
dispose_list(&dispose);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&sb->s_inode_list_lock);
|
spin_unlock(&sb->s_inode_list_lock);
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,9 @@ static void fsnotify_unmount_inodes(struct super_block *sb)
|
||||||
* doing an __iget/iput with SB_ACTIVE clear would actually
|
* doing an __iget/iput with SB_ACTIVE clear would actually
|
||||||
* evict all inodes with zero i_count from icache which is
|
* evict all inodes with zero i_count from icache which is
|
||||||
* unnecessarily violent and may in fact be illegal to do.
|
* unnecessarily violent and may in fact be illegal to do.
|
||||||
|
* However, we should have been called /after/ evict_inodes
|
||||||
|
* removed all zero refcount inodes, in any case. Test to
|
||||||
|
* be sure.
|
||||||
*/
|
*/
|
||||||
if (!atomic_read(&inode->i_count)) {
|
if (!atomic_read(&inode->i_count)) {
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
|
@ -77,6 +80,7 @@ static void fsnotify_unmount_inodes(struct super_block *sb)
|
||||||
|
|
||||||
iput_inode = inode;
|
iput_inode = inode;
|
||||||
|
|
||||||
|
cond_resched();
|
||||||
spin_lock(&sb->s_inode_list_lock);
|
spin_lock(&sb->s_inode_list_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&sb->s_inode_list_lock);
|
spin_unlock(&sb->s_inode_list_lock);
|
||||||
|
|
|
@ -984,6 +984,7 @@ static int add_dquot_ref(struct super_block *sb, int type)
|
||||||
* later.
|
* later.
|
||||||
*/
|
*/
|
||||||
old_inode = inode;
|
old_inode = inode;
|
||||||
|
cond_resched();
|
||||||
spin_lock(&sb->s_inode_list_lock);
|
spin_lock(&sb->s_inode_list_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&sb->s_inode_list_lock);
|
spin_unlock(&sb->s_inode_list_lock);
|
||||||
|
|
|
@ -448,10 +448,12 @@ void generic_shutdown_super(struct super_block *sb)
|
||||||
sync_filesystem(sb);
|
sync_filesystem(sb);
|
||||||
sb->s_flags &= ~SB_ACTIVE;
|
sb->s_flags &= ~SB_ACTIVE;
|
||||||
|
|
||||||
fsnotify_sb_delete(sb);
|
|
||||||
cgroup_writeback_umount();
|
cgroup_writeback_umount();
|
||||||
|
|
||||||
|
/* evict all inodes with zero refcount */
|
||||||
evict_inodes(sb);
|
evict_inodes(sb);
|
||||||
|
/* only nonzero refcount inodes can have marks */
|
||||||
|
fsnotify_sb_delete(sb);
|
||||||
|
|
||||||
if (sb->s_dio_done_wq) {
|
if (sb->s_dio_done_wq) {
|
||||||
destroy_workqueue(sb->s_dio_done_wq);
|
destroy_workqueue(sb->s_dio_done_wq);
|
||||||
|
|
|
@ -1222,11 +1222,12 @@ EXPORT_SYMBOL(iov_iter_discard);
|
||||||
|
|
||||||
unsigned long iov_iter_alignment(const struct iov_iter *i)
|
unsigned long iov_iter_alignment(const struct iov_iter *i)
|
||||||
{
|
{
|
||||||
unsigned int p_mask = i->pipe->ring_size - 1;
|
|
||||||
unsigned long res = 0;
|
unsigned long res = 0;
|
||||||
size_t size = i->count;
|
size_t size = i->count;
|
||||||
|
|
||||||
if (unlikely(iov_iter_is_pipe(i))) {
|
if (unlikely(iov_iter_is_pipe(i))) {
|
||||||
|
unsigned int p_mask = i->pipe->ring_size - 1;
|
||||||
|
|
||||||
if (size && i->iov_offset && allocated(&i->pipe->bufs[i->head & p_mask]))
|
if (size && i->iov_offset && allocated(&i->pipe->bufs[i->head & p_mask]))
|
||||||
return size | i->iov_offset;
|
return size | i->iov_offset;
|
||||||
return size;
|
return size;
|
||||||
|
|
Loading…
Reference in New Issue