aboutsummaryrefslogtreecommitdiffstats
path: root/fs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/inode.c')
-rw-r--r--fs/inode.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 0647d80accf6..0b3da4a77704 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -25,6 +25,7 @@
25#include <linux/async.h> 25#include <linux/async.h>
26#include <linux/posix_acl.h> 26#include <linux/posix_acl.h>
27#include <linux/ima.h> 27#include <linux/ima.h>
28#include <linux/cred.h>
28 29
29/* 30/*
30 * This is needed for the following functions: 31 * This is needed for the following functions:
@@ -84,16 +85,13 @@ static struct hlist_head *inode_hashtable __read_mostly;
84DEFINE_SPINLOCK(inode_lock); 85DEFINE_SPINLOCK(inode_lock);
85 86
86/* 87/*
87 * iprune_sem provides exclusion between the kswapd or try_to_free_pages 88 * iprune_sem provides exclusion between the icache shrinking and the
88 * icache shrinking path, and the umount path. Without this exclusion, 89 * umount path.
89 * by the time prune_icache calls iput for the inode whose pages it has
90 * been invalidating, or by the time it calls clear_inode & destroy_inode
91 * from its final dispose_list, the struct super_block they refer to
92 * (for inode->i_sb->s_op) may already have been freed and reused.
93 * 90 *
94 * We make this an rwsem because the fastpath is icache shrinking. In 91 * We don't actually need it to protect anything in the umount path,
95 * some cases a filesystem may be doing a significant amount of work in 92 * but only need to cycle through it to make sure any inode that
96 * its inode reclaim code, so this should improve parallelism. 93 * prune_icache took off the LRU list has been fully torn down by the
94 * time we are past evict_inodes.
97 */ 95 */
98static DECLARE_RWSEM(iprune_sem); 96static DECLARE_RWSEM(iprune_sem);
99 97
@@ -516,17 +514,12 @@ void evict_inodes(struct super_block *sb)
516 struct inode *inode, *next; 514 struct inode *inode, *next;
517 LIST_HEAD(dispose); 515 LIST_HEAD(dispose);
518 516
519 down_write(&iprune_sem);
520
521 spin_lock(&inode_lock); 517 spin_lock(&inode_lock);
522 list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { 518 list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) {
523 if (atomic_read(&inode->i_count)) 519 if (atomic_read(&inode->i_count))
524 continue; 520 continue;
525 521 if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE))
526 if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) {
527 WARN_ON(1);
528 continue; 522 continue;
529 }
530 523
531 inode->i_state |= I_FREEING; 524 inode->i_state |= I_FREEING;
532 525
@@ -542,6 +535,13 @@ void evict_inodes(struct super_block *sb)
542 spin_unlock(&inode_lock); 535 spin_unlock(&inode_lock);
543 536
544 dispose_list(&dispose); 537 dispose_list(&dispose);
538
539 /*
540 * Cycle through iprune_sem to make sure any inode that prune_icache
541 * moved off the list before we took the lock has been fully torn
542 * down.
543 */
544 down_write(&iprune_sem);
545 up_write(&iprune_sem); 545 up_write(&iprune_sem);
546} 546}
547 547
@@ -561,8 +561,6 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty)
561 struct inode *inode, *next; 561 struct inode *inode, *next;
562 LIST_HEAD(dispose); 562 LIST_HEAD(dispose);
563 563
564 down_write(&iprune_sem);
565
566 spin_lock(&inode_lock); 564 spin_lock(&inode_lock);
567 list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { 565 list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) {
568 if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) 566 if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE))
@@ -590,7 +588,6 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty)
590 spin_unlock(&inode_lock); 588 spin_unlock(&inode_lock);
591 589
592 dispose_list(&dispose); 590 dispose_list(&dispose);
593 up_write(&iprune_sem);
594 591
595 return busy; 592 return busy;
596} 593}
@@ -1719,7 +1716,7 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
1719EXPORT_SYMBOL(init_special_inode); 1716EXPORT_SYMBOL(init_special_inode);
1720 1717
1721/** 1718/**
1722 * Init uid,gid,mode for new inode according to posix standards 1719 * inode_init_owner - Init uid,gid,mode for new inode according to posix standards
1723 * @inode: New inode 1720 * @inode: New inode
1724 * @dir: Directory inode 1721 * @dir: Directory inode
1725 * @mode: mode of the new inode 1722 * @mode: mode of the new inode
@@ -1737,3 +1734,22 @@ void inode_init_owner(struct inode *inode, const struct inode *dir,
1737 inode->i_mode = mode; 1734 inode->i_mode = mode;
1738} 1735}
1739EXPORT_SYMBOL(inode_init_owner); 1736EXPORT_SYMBOL(inode_init_owner);
1737
1738/**
1739 * inode_owner_or_capable - check current task permissions to inode
1740 * @inode: inode being checked
1741 *
1742 * Return true if current either has CAP_FOWNER to the inode, or
1743 * owns the file.
1744 */
1745bool inode_owner_or_capable(const struct inode *inode)
1746{
1747 struct user_namespace *ns = inode_userns(inode);
1748
1749 if (current_user_ns() == ns && current_fsuid() == inode->i_uid)
1750 return true;
1751 if (ns_capable(ns, CAP_FOWNER))
1752 return true;
1753 return false;
1754}
1755EXPORT_SYMBOL(inode_owner_or_capable);