diff options
Diffstat (limited to 'fs/inode.c')
-rw-r--r-- | fs/inode.c | 62 |
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 | ||
774 | repeat: | 774 | repeat: |
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 | ||
805 | repeat: | 801 | repeat: |
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) | |||
951 | EXPORT_SYMBOL(unlock_new_inode); | 943 | EXPORT_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 | */ | ||
950 | void 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 | } | ||
966 | EXPORT_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 | */ | ||
973 | void 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 | } | ||
979 | EXPORT_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 | ||
1581 | int file_remove_suid(struct file *file) | 1613 | int file_remove_suid(struct file *file) |