diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 281c19ff7f45..6f8e16e3d6c0 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -621,11 +621,7 @@ struct address_space_operations { any basic-blocks on storage, then those blocks should be pre-read (if they haven't been read already) so that the updated blocks can be written out properly. - The page will be locked. If prepare_write wants to unlock the - page it, like readpage, may do so and return - AOP_TRUNCATED_PAGE. - In this case the prepare_write will be retried one the lock is - regained. + The page will be locked. Note: the page _must not_ be marked uptodate in this function (or anywhere else) unless it actually is uptodate right now. As diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index fd3f94d4a668..aaea55a61ea1 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -446,11 +446,9 @@ out: return rc; } -static -void ecryptfs_release_lower_page(struct page *lower_page, int page_locked) +static void ecryptfs_release_lower_page(struct page *lower_page) { - if (page_locked) - unlock_page(lower_page); + unlock_page(lower_page); page_cache_release(lower_page); } @@ -471,7 +469,6 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, const struct address_space_operations *lower_a_ops; u64 file_size; -retry: header_page = grab_cache_page(lower_inode->i_mapping, 0); if (!header_page) { ecryptfs_printk(KERN_ERR, "grab_cache_page for " @@ -482,11 +479,7 @@ retry: lower_a_ops = lower_inode->i_mapping->a_ops; rc = lower_a_ops->prepare_write(lower_file, header_page, 0, 8); if (rc) { - if (rc == AOP_TRUNCATED_PAGE) { - ecryptfs_release_lower_page(header_page, 0); - goto retry; - } else - ecryptfs_release_lower_page(header_page, 1); + ecryptfs_release_lower_page(header_page); goto out; } file_size = (u64)i_size_read(inode); @@ -500,11 +493,7 @@ retry: if (rc < 0) ecryptfs_printk(KERN_ERR, "Error commiting header page " "write\n"); - if (rc == AOP_TRUNCATED_PAGE) { - ecryptfs_release_lower_page(header_page, 0); - goto retry; - } else - ecryptfs_release_lower_page(header_page, 1); + ecryptfs_release_lower_page(header_page); lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; mark_inode_dirty_sync(inode); out: @@ -593,7 +582,6 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, { int rc = 0; -retry: *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index); if (!(*lower_page)) { rc = -EINVAL; @@ -607,16 +595,11 @@ retry: byte_offset, region_bytes); if (rc) { - if (rc == AOP_TRUNCATED_PAGE) { - ecryptfs_release_lower_page(*lower_page, 0); - goto retry; - } else { - ecryptfs_printk(KERN_ERR, "prepare_write for " - "lower_page_index = [0x%.16x] failed; rc = " - "[%d]\n", lower_page_index, rc); - ecryptfs_release_lower_page(*lower_page, 1); - (*lower_page) = NULL; - } + ecryptfs_printk(KERN_ERR, "prepare_write for " + "lower_page_index = [0x%.16x] failed; rc = " + "[%d]\n", lower_page_index, rc); + ecryptfs_release_lower_page(*lower_page); + (*lower_page) = NULL; } out: return rc; @@ -632,19 +615,16 @@ ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode, struct file *lower_file, int byte_offset, int region_size) { - int page_locked = 1; int rc = 0; rc = lower_inode->i_mapping->a_ops->commit_write( lower_file, lower_page, byte_offset, region_size); - if (rc == AOP_TRUNCATED_PAGE) - page_locked = 0; if (rc < 0) { ecryptfs_printk(KERN_ERR, "Error committing write; rc = [%d]\n", rc); } else rc = 0; - ecryptfs_release_lower_page(lower_page, page_locked); + ecryptfs_release_lower_page(lower_page); return rc; } diff --git a/include/linux/fs.h b/include/linux/fs.h index a40557eae2ed..f70d52c46617 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -381,7 +381,7 @@ struct iattr { * trying again. The aop will be taking reasonable * precautions not to livelock. If the caller held a page * reference, it should drop it before retrying. Returned - * by readpage(), prepare_write(), and commit_write(). + * by readpage(). * * address_space_operation functions return these large constants to indicate * special semantics to the caller. These are much larger than the bytes in a diff --git a/mm/filemap.c b/mm/filemap.c index 195339b27e9a..c6049e947cd9 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1898,13 +1898,10 @@ again: ret = aops->prepare_write(file, page, offset, offset+len); if (ret) { - if (ret != AOP_TRUNCATED_PAGE) - unlock_page(page); + unlock_page(page); page_cache_release(page); if (pos + len > inode->i_size) vmtruncate(inode, inode->i_size); - if (ret == AOP_TRUNCATED_PAGE) - goto again; } return ret; } @@ -1931,7 +1928,6 @@ int pagecache_write_end(struct file *file, struct address_space *mapping, unlock_page(page); mark_page_accessed(page); page_cache_release(page); - BUG_ON(ret == AOP_TRUNCATED_PAGE); /* can't deal with */ if (ret < 0) { if (pos + len > inode->i_size) @@ -2142,7 +2138,7 @@ static ssize_t generic_perform_write_2copy(struct file *file, flush_dcache_page(page); status = a_ops->commit_write(file, page, offset, offset+bytes); - if (unlikely(status < 0 || status == AOP_TRUNCATED_PAGE)) + if (unlikely(status < 0)) goto fs_write_aop_error; if (unlikely(status > 0)) /* filesystem did partial write */ copied = min_t(size_t, copied, status); @@ -2162,8 +2158,7 @@ static ssize_t generic_perform_write_2copy(struct file *file, continue; fs_write_aop_error: - if (status != AOP_TRUNCATED_PAGE) - unlock_page(page); + unlock_page(page); page_cache_release(page); if (src_page) page_cache_release(src_page); @@ -2175,10 +2170,7 @@ fs_write_aop_error: */ if (pos + bytes > inode->i_size) vmtruncate(inode, inode->i_size); - if (status == AOP_TRUNCATED_PAGE) - continue; - else - break; + break; } while (iov_iter_count(i)); return written ? written : status;