diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/fs/namei.c b/fs/namei.c index 51cfc9c3ed00..98dc2e134362 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -104,7 +104,7 @@ | |||
104 | */ | 104 | */ |
105 | /* | 105 | /* |
106 | * [Sep 2001 AV] Single-semaphore locking scheme (kudos to David Holland) | 106 | * [Sep 2001 AV] Single-semaphore locking scheme (kudos to David Holland) |
107 | * implemented. Let's see if raised priority of ->s_vfs_rename_sem gives | 107 | * implemented. Let's see if raised priority of ->s_vfs_rename_mutex gives |
108 | * any extra contention... | 108 | * any extra contention... |
109 | */ | 109 | */ |
110 | 110 | ||
@@ -1423,7 +1423,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) | |||
1423 | return NULL; | 1423 | return NULL; |
1424 | } | 1424 | } |
1425 | 1425 | ||
1426 | down(&p1->d_inode->i_sb->s_vfs_rename_sem); | 1426 | mutex_lock(&p1->d_inode->i_sb->s_vfs_rename_mutex); |
1427 | 1427 | ||
1428 | for (p = p1; p->d_parent != p; p = p->d_parent) { | 1428 | for (p = p1; p->d_parent != p; p = p->d_parent) { |
1429 | if (p->d_parent == p2) { | 1429 | if (p->d_parent == p2) { |
@@ -1451,7 +1451,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2) | |||
1451 | mutex_unlock(&p1->d_inode->i_mutex); | 1451 | mutex_unlock(&p1->d_inode->i_mutex); |
1452 | if (p1 != p2) { | 1452 | if (p1 != p2) { |
1453 | mutex_unlock(&p2->d_inode->i_mutex); | 1453 | mutex_unlock(&p2->d_inode->i_mutex); |
1454 | up(&p1->d_inode->i_sb->s_vfs_rename_sem); | 1454 | mutex_unlock(&p1->d_inode->i_sb->s_vfs_rename_mutex); |
1455 | } | 1455 | } |
1456 | } | 1456 | } |
1457 | 1457 | ||
@@ -1629,6 +1629,12 @@ do_last: | |||
1629 | goto exit; | 1629 | goto exit; |
1630 | } | 1630 | } |
1631 | 1631 | ||
1632 | if (IS_ERR(nd->intent.open.file)) { | ||
1633 | mutex_unlock(&dir->d_inode->i_mutex); | ||
1634 | error = PTR_ERR(nd->intent.open.file); | ||
1635 | goto exit_dput; | ||
1636 | } | ||
1637 | |||
1632 | /* Negative dentry, just create the file */ | 1638 | /* Negative dentry, just create the file */ |
1633 | if (!path.dentry->d_inode) { | 1639 | if (!path.dentry->d_inode) { |
1634 | if (!IS_POSIXACL(dir->d_inode)) | 1640 | if (!IS_POSIXACL(dir->d_inode)) |
@@ -2278,17 +2284,17 @@ asmlinkage long sys_link(const char __user *oldname, const char __user *newname) | |||
2278 | * a) we can get into loop creation. Check is done in is_subdir(). | 2284 | * a) we can get into loop creation. Check is done in is_subdir(). |
2279 | * b) race potential - two innocent renames can create a loop together. | 2285 | * b) race potential - two innocent renames can create a loop together. |
2280 | * That's where 4.4 screws up. Current fix: serialization on | 2286 | * That's where 4.4 screws up. Current fix: serialization on |
2281 | * sb->s_vfs_rename_sem. We might be more accurate, but that's another | 2287 | * sb->s_vfs_rename_mutex. We might be more accurate, but that's another |
2282 | * story. | 2288 | * story. |
2283 | * c) we have to lock _three_ objects - parents and victim (if it exists). | 2289 | * c) we have to lock _three_ objects - parents and victim (if it exists). |
2284 | * And that - after we got ->i_mutex on parents (until then we don't know | 2290 | * And that - after we got ->i_mutex on parents (until then we don't know |
2285 | * whether the target exists). Solution: try to be smart with locking | 2291 | * whether the target exists). Solution: try to be smart with locking |
2286 | * order for inodes. We rely on the fact that tree topology may change | 2292 | * order for inodes. We rely on the fact that tree topology may change |
2287 | * only under ->s_vfs_rename_sem _and_ that parent of the object we | 2293 | * only under ->s_vfs_rename_mutex _and_ that parent of the object we |
2288 | * move will be locked. Thus we can rank directories by the tree | 2294 | * move will be locked. Thus we can rank directories by the tree |
2289 | * (ancestors first) and rank all non-directories after them. | 2295 | * (ancestors first) and rank all non-directories after them. |
2290 | * That works since everybody except rename does "lock parent, lookup, | 2296 | * That works since everybody except rename does "lock parent, lookup, |
2291 | * lock child" and rename is under ->s_vfs_rename_sem. | 2297 | * lock child" and rename is under ->s_vfs_rename_mutex. |
2292 | * HOWEVER, it relies on the assumption that any object with ->lookup() | 2298 | * HOWEVER, it relies on the assumption that any object with ->lookup() |
2293 | * has no more than 1 dentry. If "hybrid" objects will ever appear, | 2299 | * has no more than 1 dentry. If "hybrid" objects will ever appear, |
2294 | * we'd better make sure that there's no link(2) for them. | 2300 | * we'd better make sure that there's no link(2) for them. |
@@ -2622,16 +2628,27 @@ int __page_symlink(struct inode *inode, const char *symname, int len, | |||
2622 | int err = -ENOMEM; | 2628 | int err = -ENOMEM; |
2623 | char *kaddr; | 2629 | char *kaddr; |
2624 | 2630 | ||
2631 | retry: | ||
2625 | page = find_or_create_page(mapping, 0, gfp_mask); | 2632 | page = find_or_create_page(mapping, 0, gfp_mask); |
2626 | if (!page) | 2633 | if (!page) |
2627 | goto fail; | 2634 | goto fail; |
2628 | err = mapping->a_ops->prepare_write(NULL, page, 0, len-1); | 2635 | err = mapping->a_ops->prepare_write(NULL, page, 0, len-1); |
2636 | if (err == AOP_TRUNCATED_PAGE) { | ||
2637 | page_cache_release(page); | ||
2638 | goto retry; | ||
2639 | } | ||
2629 | if (err) | 2640 | if (err) |
2630 | goto fail_map; | 2641 | goto fail_map; |
2631 | kaddr = kmap_atomic(page, KM_USER0); | 2642 | kaddr = kmap_atomic(page, KM_USER0); |
2632 | memcpy(kaddr, symname, len-1); | 2643 | memcpy(kaddr, symname, len-1); |
2633 | kunmap_atomic(kaddr, KM_USER0); | 2644 | kunmap_atomic(kaddr, KM_USER0); |
2634 | mapping->a_ops->commit_write(NULL, page, 0, len-1); | 2645 | err = mapping->a_ops->commit_write(NULL, page, 0, len-1); |
2646 | if (err == AOP_TRUNCATED_PAGE) { | ||
2647 | page_cache_release(page); | ||
2648 | goto retry; | ||
2649 | } | ||
2650 | if (err) | ||
2651 | goto fail_map; | ||
2635 | /* | 2652 | /* |
2636 | * Notice that we are _not_ going to block here - end of page is | 2653 | * Notice that we are _not_ going to block here - end of page is |
2637 | * unmapped, so this will only try to map the rest of page, see | 2654 | * unmapped, so this will only try to map the rest of page, see |
@@ -2641,7 +2658,8 @@ int __page_symlink(struct inode *inode, const char *symname, int len, | |||
2641 | */ | 2658 | */ |
2642 | if (!PageUptodate(page)) { | 2659 | if (!PageUptodate(page)) { |
2643 | err = mapping->a_ops->readpage(NULL, page); | 2660 | err = mapping->a_ops->readpage(NULL, page); |
2644 | wait_on_page_locked(page); | 2661 | if (err != AOP_TRUNCATED_PAGE) |
2662 | wait_on_page_locked(page); | ||
2645 | } else { | 2663 | } else { |
2646 | unlock_page(page); | 2664 | unlock_page(page); |
2647 | } | 2665 | } |