Commit 205c109a authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds

jffs2: convert to new aops

Signed-off-by: default avatarNick Piggin <npiggin@suse.de>
Cc: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ae361ff4
...@@ -19,10 +19,12 @@ ...@@ -19,10 +19,12 @@
#include <linux/jffs2.h> #include <linux/jffs2.h>
#include "nodelist.h" #include "nodelist.h"
static int jffs2_commit_write (struct file *filp, struct page *pg, static int jffs2_write_end(struct file *filp, struct address_space *mapping,
unsigned start, unsigned end); loff_t pos, unsigned len, unsigned copied,
static int jffs2_prepare_write (struct file *filp, struct page *pg, struct page *pg, void *fsdata);
unsigned start, unsigned end); static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata);
static int jffs2_readpage (struct file *filp, struct page *pg); static int jffs2_readpage (struct file *filp, struct page *pg);
int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync)
...@@ -65,8 +67,8 @@ const struct inode_operations jffs2_file_inode_operations = ...@@ -65,8 +67,8 @@ const struct inode_operations jffs2_file_inode_operations =
const struct address_space_operations jffs2_file_address_operations = const struct address_space_operations jffs2_file_address_operations =
{ {
.readpage = jffs2_readpage, .readpage = jffs2_readpage,
.prepare_write =jffs2_prepare_write, .write_begin = jffs2_write_begin,
.commit_write = jffs2_commit_write .write_end = jffs2_write_end,
}; };
static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg) static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
...@@ -119,15 +121,23 @@ static int jffs2_readpage (struct file *filp, struct page *pg) ...@@ -119,15 +121,23 @@ static int jffs2_readpage (struct file *filp, struct page *pg)
return ret; return ret;
} }
static int jffs2_prepare_write (struct file *filp, struct page *pg, static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
unsigned start, unsigned end) loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata)
{ {
struct inode *inode = pg->mapping->host; struct page *pg;
struct inode *inode = mapping->host;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT; pgoff_t index = pos >> PAGE_CACHE_SHIFT;
uint32_t pageofs = pos & (PAGE_CACHE_SIZE - 1);
int ret = 0; int ret = 0;
D1(printk(KERN_DEBUG "jffs2_prepare_write()\n")); pg = __grab_cache_page(mapping, index);
if (!pg)
return -ENOMEM;
*pagep = pg;
D1(printk(KERN_DEBUG "jffs2_write_begin()\n"));
if (pageofs > inode->i_size) { if (pageofs > inode->i_size) {
/* Make new hole frag from old EOF to new page */ /* Make new hole frag from old EOF to new page */
...@@ -142,7 +152,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, ...@@ -142,7 +152,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
if (ret) if (ret)
return ret; goto out_page;
down(&f->sem); down(&f->sem);
memset(&ri, 0, sizeof(ri)); memset(&ri, 0, sizeof(ri));
...@@ -172,7 +182,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, ...@@ -172,7 +182,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
ret = PTR_ERR(fn); ret = PTR_ERR(fn);
jffs2_complete_reservation(c); jffs2_complete_reservation(c);
up(&f->sem); up(&f->sem);
return ret; goto out_page;
} }
ret = jffs2_add_full_dnode_to_inode(c, f, fn); ret = jffs2_add_full_dnode_to_inode(c, f, fn);
if (f->metadata) { if (f->metadata) {
...@@ -181,65 +191,79 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, ...@@ -181,65 +191,79 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
f->metadata = NULL; f->metadata = NULL;
} }
if (ret) { if (ret) {
D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret)); D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in write_begin, returned %d\n", ret));
jffs2_mark_node_obsolete(c, fn->raw); jffs2_mark_node_obsolete(c, fn->raw);
jffs2_free_full_dnode(fn); jffs2_free_full_dnode(fn);
jffs2_complete_reservation(c); jffs2_complete_reservation(c);
up(&f->sem); up(&f->sem);
return ret; goto out_page;
} }
jffs2_complete_reservation(c); jffs2_complete_reservation(c);
inode->i_size = pageofs; inode->i_size = pageofs;
up(&f->sem); up(&f->sem);
} }
/* Read in the page if it wasn't already present, unless it's a whole page */ /*
if (!PageUptodate(pg) && (start || end < PAGE_CACHE_SIZE)) { * Read in the page if it wasn't already present. Cannot optimize away
* the whole page write case until jffs2_write_end can handle the
* case of a short-copy.
*/
if (!PageUptodate(pg)) {
down(&f->sem); down(&f->sem);
ret = jffs2_do_readpage_nolock(inode, pg); ret = jffs2_do_readpage_nolock(inode, pg);
up(&f->sem); up(&f->sem);
if (ret)
goto out_page;
} }
D1(printk(KERN_DEBUG "end prepare_write(). pg->flags %lx\n", pg->flags)); D1(printk(KERN_DEBUG "end write_begin(). pg->flags %lx\n", pg->flags));
return ret;
out_page:
unlock_page(pg);
page_cache_release(pg);
return ret; return ret;
} }
static int jffs2_commit_write (struct file *filp, struct page *pg, static int jffs2_write_end(struct file *filp, struct address_space *mapping,
unsigned start, unsigned end) loff_t pos, unsigned len, unsigned copied,
struct page *pg, void *fsdata)
{ {
/* Actually commit the write from the page cache page we're looking at. /* Actually commit the write from the page cache page we're looking at.
* For now, we write the full page out each time. It sucks, but it's simple * For now, we write the full page out each time. It sucks, but it's simple
*/ */
struct inode *inode = pg->mapping->host; struct inode *inode = mapping->host;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
struct jffs2_raw_inode *ri; struct jffs2_raw_inode *ri;
unsigned start = pos & (PAGE_CACHE_SIZE - 1);
unsigned end = start + copied;
unsigned aligned_start = start & ~3; unsigned aligned_start = start & ~3;
int ret = 0; int ret = 0;
uint32_t writtenlen = 0; uint32_t writtenlen = 0;
D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", D1(printk(KERN_DEBUG "jffs2_write_end(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n",
inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags));
/* We need to avoid deadlock with page_cache_read() in
jffs2_garbage_collect_pass(). So the page must be
up to date to prevent page_cache_read() from trying
to re-lock it. */
BUG_ON(!PageUptodate(pg));
if (end == PAGE_CACHE_SIZE) { if (end == PAGE_CACHE_SIZE) {
if (!start) { /* When writing out the end of a page, write out the
/* We need to avoid deadlock with page_cache_read() in _whole_ page. This helps to reduce the number of
jffs2_garbage_collect_pass(). So we have to mark the nodes in files which have many short writes, like
page up to date, to prevent page_cache_read() from syslog files. */
trying to re-lock it. */ start = aligned_start = 0;
SetPageUptodate(pg);
} else {
/* When writing out the end of a page, write out the
_whole_ page. This helps to reduce the number of
nodes in files which have many short writes, like
syslog files. */
start = aligned_start = 0;
}
} }
ri = jffs2_alloc_raw_inode(); ri = jffs2_alloc_raw_inode();
if (!ri) { if (!ri) {
D1(printk(KERN_DEBUG "jffs2_commit_write(): Allocation of raw inode failed\n")); D1(printk(KERN_DEBUG "jffs2_write_end(): Allocation of raw inode failed\n"));
unlock_page(pg);
page_cache_release(pg);
return -ENOMEM; return -ENOMEM;
} }
...@@ -287,11 +311,14 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, ...@@ -287,11 +311,14 @@ static int jffs2_commit_write (struct file *filp, struct page *pg,
/* generic_file_write has written more to the page cache than we've /* generic_file_write has written more to the page cache than we've
actually written to the medium. Mark the page !Uptodate so that actually written to the medium. Mark the page !Uptodate so that
it gets reread */ it gets reread */
D1(printk(KERN_DEBUG "jffs2_commit_write(): Not all bytes written. Marking page !uptodate\n")); D1(printk(KERN_DEBUG "jffs2_write_end(): Not all bytes written. Marking page !uptodate\n"));
SetPageError(pg); SetPageError(pg);
ClearPageUptodate(pg); ClearPageUptodate(pg);
} }
D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d\n",start+writtenlen==end?0:ret)); D1(printk(KERN_DEBUG "jffs2_write_end() returning %d\n",
return start+writtenlen==end?0:ret; writtenlen > 0 ? writtenlen : ret));
unlock_page(pg);
page_cache_release(pg);
return writtenlen > 0 ? writtenlen : ret;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment