aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/jffs2/file.c105
1 files changed, 66 insertions, 39 deletions
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index c2530197be0c..023a17539dd4 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -19,10 +19,12 @@
19#include <linux/jffs2.h> 19#include <linux/jffs2.h>
20#include "nodelist.h" 20#include "nodelist.h"
21 21
22static int jffs2_commit_write (struct file *filp, struct page *pg, 22static int jffs2_write_end(struct file *filp, struct address_space *mapping,
23 unsigned start, unsigned end); 23 loff_t pos, unsigned len, unsigned copied,
24static int jffs2_prepare_write (struct file *filp, struct page *pg, 24 struct page *pg, void *fsdata);
25 unsigned start, unsigned end); 25static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
26 loff_t pos, unsigned len, unsigned flags,
27 struct page **pagep, void **fsdata);
26static int jffs2_readpage (struct file *filp, struct page *pg); 28static int jffs2_readpage (struct file *filp, struct page *pg);
27 29
28int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) 30int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync)
@@ -65,8 +67,8 @@ const struct inode_operations jffs2_file_inode_operations =
65const struct address_space_operations jffs2_file_address_operations = 67const struct address_space_operations jffs2_file_address_operations =
66{ 68{
67 .readpage = jffs2_readpage, 69 .readpage = jffs2_readpage,
68 .prepare_write =jffs2_prepare_write, 70 .write_begin = jffs2_write_begin,
69 .commit_write = jffs2_commit_write 71 .write_end = jffs2_write_end,
70}; 72};
71 73
72static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg) 74static 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 return ret; 121 return ret;
120} 122}
121 123
122static int jffs2_prepare_write (struct file *filp, struct page *pg, 124static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
123 unsigned start, unsigned end) 125 loff_t pos, unsigned len, unsigned flags,
126 struct page **pagep, void **fsdata)
124{ 127{
125 struct inode *inode = pg->mapping->host; 128 struct page *pg;
129 struct inode *inode = mapping->host;
126 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 130 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
127 uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT; 131 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
132 uint32_t pageofs = pos & (PAGE_CACHE_SIZE - 1);
128 int ret = 0; 133 int ret = 0;
129 134
130 D1(printk(KERN_DEBUG "jffs2_prepare_write()\n")); 135 pg = __grab_cache_page(mapping, index);
136 if (!pg)
137 return -ENOMEM;
138 *pagep = pg;
139
140 D1(printk(KERN_DEBUG "jffs2_write_begin()\n"));
131 141
132 if (pageofs > inode->i_size) { 142 if (pageofs > inode->i_size) {
133 /* Make new hole frag from old EOF to new page */ 143 /* 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 ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, 152 ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
143 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 153 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
144 if (ret) 154 if (ret)
145 return ret; 155 goto out_page;
146 156
147 down(&f->sem); 157 down(&f->sem);
148 memset(&ri, 0, sizeof(ri)); 158 memset(&ri, 0, sizeof(ri));
@@ -172,7 +182,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
172 ret = PTR_ERR(fn); 182 ret = PTR_ERR(fn);
173 jffs2_complete_reservation(c); 183 jffs2_complete_reservation(c);
174 up(&f->sem); 184 up(&f->sem);
175 return ret; 185 goto out_page;
176 } 186 }
177 ret = jffs2_add_full_dnode_to_inode(c, f, fn); 187 ret = jffs2_add_full_dnode_to_inode(c, f, fn);
178 if (f->metadata) { 188 if (f->metadata) {
@@ -181,65 +191,79 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
181 f->metadata = NULL; 191 f->metadata = NULL;
182 } 192 }
183 if (ret) { 193 if (ret) {
184 D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret)); 194 D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in write_begin, returned %d\n", ret));
185 jffs2_mark_node_obsolete(c, fn->raw); 195 jffs2_mark_node_obsolete(c, fn->raw);
186 jffs2_free_full_dnode(fn); 196 jffs2_free_full_dnode(fn);
187 jffs2_complete_reservation(c); 197 jffs2_complete_reservation(c);
188 up(&f->sem); 198 up(&f->sem);
189 return ret; 199 goto out_page;
190 } 200 }
191 jffs2_complete_reservation(c); 201 jffs2_complete_reservation(c);
192 inode->i_size = pageofs; 202 inode->i_size = pageofs;
193 up(&f->sem); 203 up(&f->sem);
194 } 204 }
195 205
196 /* Read in the page if it wasn't already present, unless it's a whole page */ 206 /*
197 if (!PageUptodate(pg) && (start || end < PAGE_CACHE_SIZE)) { 207 * Read in the page if it wasn't already present. Cannot optimize away
208 * the whole page write case until jffs2_write_end can handle the
209 * case of a short-copy.
210 */
211 if (!PageUptodate(pg)) {
198 down(&f->sem); 212 down(&f->sem);
199 ret = jffs2_do_readpage_nolock(inode, pg); 213 ret = jffs2_do_readpage_nolock(inode, pg);
200 up(&f->sem); 214 up(&f->sem);
215 if (ret)
216 goto out_page;
201 } 217 }
202 D1(printk(KERN_DEBUG "end prepare_write(). pg->flags %lx\n", pg->flags)); 218 D1(printk(KERN_DEBUG "end write_begin(). pg->flags %lx\n", pg->flags));
219 return ret;
220
221out_page:
222 unlock_page(pg);
223 page_cache_release(pg);
203 return ret; 224 return ret;
204} 225}
205 226
206static int jffs2_commit_write (struct file *filp, struct page *pg, 227static int jffs2_write_end(struct file *filp, struct address_space *mapping,
207 unsigned start, unsigned end) 228 loff_t pos, unsigned len, unsigned copied,
229 struct page *pg, void *fsdata)
208{ 230{
209 /* Actually commit the write from the page cache page we're looking at. 231 /* Actually commit the write from the page cache page we're looking at.
210 * For now, we write the full page out each time. It sucks, but it's simple 232 * For now, we write the full page out each time. It sucks, but it's simple
211 */ 233 */
212 struct inode *inode = pg->mapping->host; 234 struct inode *inode = mapping->host;
213 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 235 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
214 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 236 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
215 struct jffs2_raw_inode *ri; 237 struct jffs2_raw_inode *ri;
238 unsigned start = pos & (PAGE_CACHE_SIZE - 1);
239 unsigned end = start + copied;
216 unsigned aligned_start = start & ~3; 240 unsigned aligned_start = start & ~3;
217 int ret = 0; 241 int ret = 0;
218 uint32_t writtenlen = 0; 242 uint32_t writtenlen = 0;
219 243
220 D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", 244 D1(printk(KERN_DEBUG "jffs2_write_end(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n",
221 inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); 245 inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags));
222 246
247 /* We need to avoid deadlock with page_cache_read() in
248 jffs2_garbage_collect_pass(). So the page must be
249 up to date to prevent page_cache_read() from trying
250 to re-lock it. */
251 BUG_ON(!PageUptodate(pg));
252
223 if (end == PAGE_CACHE_SIZE) { 253 if (end == PAGE_CACHE_SIZE) {
224 if (!start) { 254 /* When writing out the end of a page, write out the
225 /* We need to avoid deadlock with page_cache_read() in 255 _whole_ page. This helps to reduce the number of
226 jffs2_garbage_collect_pass(). So we have to mark the 256 nodes in files which have many short writes, like
227 page up to date, to prevent page_cache_read() from 257 syslog files. */
228 trying to re-lock it. */ 258 start = aligned_start = 0;
229 SetPageUptodate(pg);
230 } else {
231 /* When writing out the end of a page, write out the
232 _whole_ page. This helps to reduce the number of
233 nodes in files which have many short writes, like
234 syslog files. */
235 start = aligned_start = 0;
236 }
237 } 259 }
238 260
239 ri = jffs2_alloc_raw_inode(); 261 ri = jffs2_alloc_raw_inode();
240 262
241 if (!ri) { 263 if (!ri) {
242 D1(printk(KERN_DEBUG "jffs2_commit_write(): Allocation of raw inode failed\n")); 264 D1(printk(KERN_DEBUG "jffs2_write_end(): Allocation of raw inode failed\n"));
265 unlock_page(pg);
266 page_cache_release(pg);
243 return -ENOMEM; 267 return -ENOMEM;
244 } 268 }
245 269
@@ -287,11 +311,14 @@ static int jffs2_commit_write (struct file *filp, struct page *pg,
287 /* generic_file_write has written more to the page cache than we've 311 /* generic_file_write has written more to the page cache than we've
288 actually written to the medium. Mark the page !Uptodate so that 312 actually written to the medium. Mark the page !Uptodate so that
289 it gets reread */ 313 it gets reread */
290 D1(printk(KERN_DEBUG "jffs2_commit_write(): Not all bytes written. Marking page !uptodate\n")); 314 D1(printk(KERN_DEBUG "jffs2_write_end(): Not all bytes written. Marking page !uptodate\n"));
291 SetPageError(pg); 315 SetPageError(pg);
292 ClearPageUptodate(pg); 316 ClearPageUptodate(pg);
293 } 317 }
294 318
295 D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d\n",start+writtenlen==end?0:ret)); 319 D1(printk(KERN_DEBUG "jffs2_write_end() returning %d\n",
296 return start+writtenlen==end?0:ret; 320 writtenlen > 0 ? writtenlen : ret));
321 unlock_page(pg);
322 page_cache_release(pg);
323 return writtenlen > 0 ? writtenlen : ret;
297} 324}