[PATCH] Honour AOP_TRUNCATE_PAGE returns in page_symlink
As prepare_write, commit_write and readpage are allowed to return AOP_TRUNCATE_PAGE, page_symlink should respond to them. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
341546f5ad
commit
7e53cac41d
1 changed files with 14 additions and 2 deletions
16
fs/namei.c
16
fs/namei.c
|
@ -2627,16 +2627,27 @@ int __page_symlink(struct inode *inode, const char *symname, int len,
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
char *kaddr;
|
char *kaddr;
|
||||||
|
|
||||||
|
retry:
|
||||||
page = find_or_create_page(mapping, 0, gfp_mask);
|
page = find_or_create_page(mapping, 0, gfp_mask);
|
||||||
if (!page)
|
if (!page)
|
||||||
goto fail;
|
goto fail;
|
||||||
err = mapping->a_ops->prepare_write(NULL, page, 0, len-1);
|
err = mapping->a_ops->prepare_write(NULL, page, 0, len-1);
|
||||||
|
if (err == AOP_TRUNCATED_PAGE) {
|
||||||
|
page_cache_release(page);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
if (err)
|
if (err)
|
||||||
goto fail_map;
|
goto fail_map;
|
||||||
kaddr = kmap_atomic(page, KM_USER0);
|
kaddr = kmap_atomic(page, KM_USER0);
|
||||||
memcpy(kaddr, symname, len-1);
|
memcpy(kaddr, symname, len-1);
|
||||||
kunmap_atomic(kaddr, KM_USER0);
|
kunmap_atomic(kaddr, KM_USER0);
|
||||||
mapping->a_ops->commit_write(NULL, page, 0, len-1);
|
err = mapping->a_ops->commit_write(NULL, page, 0, len-1);
|
||||||
|
if (err == AOP_TRUNCATED_PAGE) {
|
||||||
|
page_cache_release(page);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
|
goto fail_map;
|
||||||
/*
|
/*
|
||||||
* Notice that we are _not_ going to block here - end of page is
|
* Notice that we are _not_ going to block here - end of page is
|
||||||
* unmapped, so this will only try to map the rest of page, see
|
* unmapped, so this will only try to map the rest of page, see
|
||||||
|
@ -2646,7 +2657,8 @@ int __page_symlink(struct inode *inode, const char *symname, int len,
|
||||||
*/
|
*/
|
||||||
if (!PageUptodate(page)) {
|
if (!PageUptodate(page)) {
|
||||||
err = mapping->a_ops->readpage(NULL, page);
|
err = mapping->a_ops->readpage(NULL, page);
|
||||||
wait_on_page_locked(page);
|
if (err != AOP_TRUNCATED_PAGE)
|
||||||
|
wait_on_page_locked(page);
|
||||||
} else {
|
} else {
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue