diff options
-rw-r--r-- | drivers/usb/core/inode.c | 2 | ||||
-rw-r--r-- | fs/namei.c | 20 | ||||
-rw-r--r-- | include/linux/fs.h | 19 |
3 files changed, 30 insertions, 11 deletions
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index e47e3a8ed6e4..cf11196e012d 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
@@ -200,7 +200,7 @@ static void update_sb(struct super_block *sb) | |||
200 | if (!root) | 200 | if (!root) |
201 | return; | 201 | return; |
202 | 202 | ||
203 | mutex_lock(&root->d_inode->i_mutex); | 203 | mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_PARENT); |
204 | 204 | ||
205 | list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) { | 205 | list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) { |
206 | if (bus->d_inode) { | 206 | if (bus->d_inode) { |
diff --git a/fs/namei.c b/fs/namei.c index c784e8bb57a3..c9750d755aff 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1423,7 +1423,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) | |||
1423 | struct dentry *p; | 1423 | struct dentry *p; |
1424 | 1424 | ||
1425 | if (p1 == p2) { | 1425 | if (p1 == p2) { |
1426 | mutex_lock(&p1->d_inode->i_mutex); | 1426 | mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT); |
1427 | return NULL; | 1427 | return NULL; |
1428 | } | 1428 | } |
1429 | 1429 | ||
@@ -1431,22 +1431,22 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) | |||
1431 | 1431 | ||
1432 | for (p = p1; p->d_parent != p; p = p->d_parent) { | 1432 | for (p = p1; p->d_parent != p; p = p->d_parent) { |
1433 | if (p->d_parent == p2) { | 1433 | if (p->d_parent == p2) { |
1434 | mutex_lock(&p2->d_inode->i_mutex); | 1434 | mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_PARENT); |
1435 | mutex_lock(&p1->d_inode->i_mutex); | 1435 | mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_CHILD); |
1436 | return p; | 1436 | return p; |
1437 | } | 1437 | } |
1438 | } | 1438 | } |
1439 | 1439 | ||
1440 | for (p = p2; p->d_parent != p; p = p->d_parent) { | 1440 | for (p = p2; p->d_parent != p; p = p->d_parent) { |
1441 | if (p->d_parent == p1) { | 1441 | if (p->d_parent == p1) { |
1442 | mutex_lock(&p1->d_inode->i_mutex); | 1442 | mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT); |
1443 | mutex_lock(&p2->d_inode->i_mutex); | 1443 | mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD); |
1444 | return p; | 1444 | return p; |
1445 | } | 1445 | } |
1446 | } | 1446 | } |
1447 | 1447 | ||
1448 | mutex_lock(&p1->d_inode->i_mutex); | 1448 | mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT); |
1449 | mutex_lock(&p2->d_inode->i_mutex); | 1449 | mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD); |
1450 | return NULL; | 1450 | return NULL; |
1451 | } | 1451 | } |
1452 | 1452 | ||
@@ -1751,7 +1751,7 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir) | |||
1751 | { | 1751 | { |
1752 | struct dentry *dentry = ERR_PTR(-EEXIST); | 1752 | struct dentry *dentry = ERR_PTR(-EEXIST); |
1753 | 1753 | ||
1754 | mutex_lock(&nd->dentry->d_inode->i_mutex); | 1754 | mutex_lock_nested(&nd->dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
1755 | /* | 1755 | /* |
1756 | * Yucky last component or no last component at all? | 1756 | * Yucky last component or no last component at all? |
1757 | * (foo/., foo/.., /////) | 1757 | * (foo/., foo/.., /////) |
@@ -2008,7 +2008,7 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
2008 | error = -EBUSY; | 2008 | error = -EBUSY; |
2009 | goto exit1; | 2009 | goto exit1; |
2010 | } | 2010 | } |
2011 | mutex_lock(&nd.dentry->d_inode->i_mutex); | 2011 | mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
2012 | dentry = lookup_hash(&nd); | 2012 | dentry = lookup_hash(&nd); |
2013 | error = PTR_ERR(dentry); | 2013 | error = PTR_ERR(dentry); |
2014 | if (!IS_ERR(dentry)) { | 2014 | if (!IS_ERR(dentry)) { |
@@ -2082,7 +2082,7 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
2082 | error = -EISDIR; | 2082 | error = -EISDIR; |
2083 | if (nd.last_type != LAST_NORM) | 2083 | if (nd.last_type != LAST_NORM) |
2084 | goto exit1; | 2084 | goto exit1; |
2085 | mutex_lock(&nd.dentry->d_inode->i_mutex); | 2085 | mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
2086 | dentry = lookup_hash(&nd); | 2086 | dentry = lookup_hash(&nd); |
2087 | error = PTR_ERR(dentry); | 2087 | error = PTR_ERR(dentry); |
2088 | if (!IS_ERR(dentry)) { | 2088 | if (!IS_ERR(dentry)) { |
diff --git a/include/linux/fs.h b/include/linux/fs.h index e04a5cfe874f..05ded9e76b23 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -543,6 +543,25 @@ struct inode { | |||
543 | }; | 543 | }; |
544 | 544 | ||
545 | /* | 545 | /* |
546 | * inode->i_mutex nesting subclasses for the lock validator: | ||
547 | * | ||
548 | * 0: the object of the current VFS operation | ||
549 | * 1: parent | ||
550 | * 2: child/target | ||
551 | * 3: quota file | ||
552 | * | ||
553 | * The locking order between these classes is | ||
554 | * parent -> child -> normal -> quota | ||
555 | */ | ||
556 | enum inode_i_mutex_lock_class | ||
557 | { | ||
558 | I_MUTEX_NORMAL, | ||
559 | I_MUTEX_PARENT, | ||
560 | I_MUTEX_CHILD, | ||
561 | I_MUTEX_QUOTA | ||
562 | }; | ||
563 | |||
564 | /* | ||
546 | * NOTE: in a 32bit arch with a preemptable kernel and | 565 | * NOTE: in a 32bit arch with a preemptable kernel and |
547 | * an UP compile the i_size_read/write must be atomic | 566 | * an UP compile the i_size_read/write must be atomic |
548 | * with respect to the local cpu (unlike with preempt disabled), | 567 | * with respect to the local cpu (unlike with preempt disabled), |