summaryrefslogtreecommitdiff
path: root/fs/namei.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-03-25 03:07:57 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-25 08:22:58 -0800
commit7e53cac41da9ebb9be774220c1b2615182667c9d (patch)
treee7da5e8189ed1949d091d28e132736542352b739 /fs/namei.c
parent341546f5ad6fce584531f744853a5807a140f2a9 (diff)
[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>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 1baf1b06fe4..712dfc77793 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2627,16 +2627,27 @@ int __page_symlink(struct inode *inode, const char *symname, int len,
int err = -ENOMEM;
char *kaddr;
+retry:
page = find_or_create_page(mapping, 0, gfp_mask);
if (!page)
goto fail;
err = mapping->a_ops->prepare_write(NULL, page, 0, len-1);
+ if (err == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto retry;
+ }
if (err)
goto fail_map;
kaddr = kmap_atomic(page, KM_USER0);
memcpy(kaddr, symname, len-1);
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
* 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)) {
err = mapping->a_ops->readpage(NULL, page);
- wait_on_page_locked(page);
+ if (err != AOP_TRUNCATED_PAGE)
+ wait_on_page_locked(page);
} else {
unlock_page(page);
}