aboutsummaryrefslogtreecommitdiffstats
path: root/fs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/inode.c')
-rw-r--r--fs/inode.c62
1 files changed, 47 insertions, 15 deletions
diff --git a/fs/inode.c b/fs/inode.c
index b33ba8e021cc..4bcdad3c9361 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -773,15 +773,11 @@ static struct inode *find_inode(struct super_block *sb,
773 773
774repeat: 774repeat:
775 hlist_for_each_entry(inode, head, i_hash) { 775 hlist_for_each_entry(inode, head, i_hash) {
776 spin_lock(&inode->i_lock); 776 if (inode->i_sb != sb)
777 if (inode->i_sb != sb) {
778 spin_unlock(&inode->i_lock);
779 continue; 777 continue;
780 } 778 if (!test(inode, data))
781 if (!test(inode, data)) {
782 spin_unlock(&inode->i_lock);
783 continue; 779 continue;
784 } 780 spin_lock(&inode->i_lock);
785 if (inode->i_state & (I_FREEING|I_WILL_FREE)) { 781 if (inode->i_state & (I_FREEING|I_WILL_FREE)) {
786 __wait_on_freeing_inode(inode); 782 __wait_on_freeing_inode(inode);
787 goto repeat; 783 goto repeat;
@@ -804,15 +800,11 @@ static struct inode *find_inode_fast(struct super_block *sb,
804 800
805repeat: 801repeat:
806 hlist_for_each_entry(inode, head, i_hash) { 802 hlist_for_each_entry(inode, head, i_hash) {
807 spin_lock(&inode->i_lock); 803 if (inode->i_ino != ino)
808 if (inode->i_ino != ino) {
809 spin_unlock(&inode->i_lock);
810 continue; 804 continue;
811 } 805 if (inode->i_sb != sb)
812 if (inode->i_sb != sb) {
813 spin_unlock(&inode->i_lock);
814 continue; 806 continue;
815 } 807 spin_lock(&inode->i_lock);
816 if (inode->i_state & (I_FREEING|I_WILL_FREE)) { 808 if (inode->i_state & (I_FREEING|I_WILL_FREE)) {
817 __wait_on_freeing_inode(inode); 809 __wait_on_freeing_inode(inode);
818 goto repeat; 810 goto repeat;
@@ -951,6 +943,42 @@ void unlock_new_inode(struct inode *inode)
951EXPORT_SYMBOL(unlock_new_inode); 943EXPORT_SYMBOL(unlock_new_inode);
952 944
953/** 945/**
946 * lock_two_nondirectories - take two i_mutexes on non-directory objects
947 * @inode1: first inode to lock
948 * @inode2: second inode to lock
949 */
950void lock_two_nondirectories(struct inode *inode1, struct inode *inode2)
951{
952 WARN_ON_ONCE(S_ISDIR(inode1->i_mode));
953 if (inode1 == inode2 || !inode2) {
954 mutex_lock(&inode1->i_mutex);
955 return;
956 }
957 WARN_ON_ONCE(S_ISDIR(inode2->i_mode));
958 if (inode1 < inode2) {
959 mutex_lock(&inode1->i_mutex);
960 mutex_lock_nested(&inode2->i_mutex, I_MUTEX_NONDIR2);
961 } else {
962 mutex_lock(&inode2->i_mutex);
963 mutex_lock_nested(&inode1->i_mutex, I_MUTEX_NONDIR2);
964 }
965}
966EXPORT_SYMBOL(lock_two_nondirectories);
967
968/**
969 * unlock_two_nondirectories - release locks from lock_two_nondirectories()
970 * @inode1: first inode to unlock
971 * @inode2: second inode to unlock
972 */
973void unlock_two_nondirectories(struct inode *inode1, struct inode *inode2)
974{
975 mutex_unlock(&inode1->i_mutex);
976 if (inode2 && inode2 != inode1)
977 mutex_unlock(&inode2->i_mutex);
978}
979EXPORT_SYMBOL(unlock_two_nondirectories);
980
981/**
954 * iget5_locked - obtain an inode from a mounted file system 982 * iget5_locked - obtain an inode from a mounted file system
955 * @sb: super block of file system 983 * @sb: super block of file system
956 * @hashval: hash value (usually inode number) to get 984 * @hashval: hash value (usually inode number) to get
@@ -1575,7 +1603,11 @@ static int __remove_suid(struct dentry *dentry, int kill)
1575 struct iattr newattrs; 1603 struct iattr newattrs;
1576 1604
1577 newattrs.ia_valid = ATTR_FORCE | kill; 1605 newattrs.ia_valid = ATTR_FORCE | kill;
1578 return notify_change(dentry, &newattrs); 1606 /*
1607 * Note we call this on write, so notify_change will not
1608 * encounter any conflicting delegations:
1609 */
1610 return notify_change(dentry, &newattrs, NULL);
1579} 1611}
1580 1612
1581int file_remove_suid(struct file *file) 1613int file_remove_suid(struct file *file)