aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/fs.c')
-rw-r--r--fs/jffs2/fs.c56
1 files changed, 35 insertions, 21 deletions
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index d2e06f7ea96f..6d1eaddde0ec 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -230,16 +230,23 @@ void jffs2_clear_inode (struct inode *inode)
230 jffs2_do_clear_inode(c, f); 230 jffs2_do_clear_inode(c, f);
231} 231}
232 232
233void jffs2_read_inode (struct inode *inode) 233struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
234{ 234{
235 struct jffs2_inode_info *f; 235 struct jffs2_inode_info *f;
236 struct jffs2_sb_info *c; 236 struct jffs2_sb_info *c;
237 struct jffs2_raw_inode latest_node; 237 struct jffs2_raw_inode latest_node;
238 union jffs2_device_node jdev; 238 union jffs2_device_node jdev;
239 struct inode *inode;
239 dev_t rdev = 0; 240 dev_t rdev = 0;
240 int ret; 241 int ret;
241 242
242 D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); 243 D1(printk(KERN_DEBUG "jffs2_iget(): ino == %lu\n", ino));
244
245 inode = iget_locked(sb, ino);
246 if (!inode)
247 return ERR_PTR(-ENOMEM);
248 if (!(inode->i_state & I_NEW))
249 return inode;
243 250
244 f = JFFS2_INODE_INFO(inode); 251 f = JFFS2_INODE_INFO(inode);
245 c = JFFS2_SB_INFO(inode->i_sb); 252 c = JFFS2_SB_INFO(inode->i_sb);
@@ -250,9 +257,9 @@ void jffs2_read_inode (struct inode *inode)
250 ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); 257 ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
251 258
252 if (ret) { 259 if (ret) {
253 make_bad_inode(inode);
254 up(&f->sem); 260 up(&f->sem);
255 return; 261 iget_failed(inode);
262 return ERR_PTR(ret);
256 } 263 }
257 inode->i_mode = jemode_to_cpu(latest_node.mode); 264 inode->i_mode = jemode_to_cpu(latest_node.mode);
258 inode->i_uid = je16_to_cpu(latest_node.uid); 265 inode->i_uid = je16_to_cpu(latest_node.uid);
@@ -303,19 +310,14 @@ void jffs2_read_inode (struct inode *inode)
303 if (f->metadata->size != sizeof(jdev.old) && 310 if (f->metadata->size != sizeof(jdev.old) &&
304 f->metadata->size != sizeof(jdev.new)) { 311 f->metadata->size != sizeof(jdev.new)) {
305 printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size); 312 printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size);
306 up(&f->sem); 313 goto error_io;
307 jffs2_do_clear_inode(c, f);
308 make_bad_inode(inode);
309 return;
310 } 314 }
311 D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); 315 D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));
312 if (jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size) < 0) { 316 ret = jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size);
317 if (ret < 0) {
313 /* Eep */ 318 /* Eep */
314 printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); 319 printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
315 up(&f->sem); 320 goto error;
316 jffs2_do_clear_inode(c, f);
317 make_bad_inode(inode);
318 return;
319 } 321 }
320 if (f->metadata->size == sizeof(jdev.old)) 322 if (f->metadata->size == sizeof(jdev.old))
321 rdev = old_decode_dev(je16_to_cpu(jdev.old)); 323 rdev = old_decode_dev(je16_to_cpu(jdev.old));
@@ -335,6 +337,16 @@ void jffs2_read_inode (struct inode *inode)
335 up(&f->sem); 337 up(&f->sem);
336 338
337 D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); 339 D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
340 unlock_new_inode(inode);
341 return inode;
342
343error_io:
344 ret = -EIO;
345error:
346 up(&f->sem);
347 jffs2_do_clear_inode(c, f);
348 iget_failed(inode);
349 return ERR_PTR(ret);
338} 350}
339 351
340void jffs2_dirty_inode(struct inode *inode) 352void jffs2_dirty_inode(struct inode *inode)
@@ -522,15 +534,16 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
522 if ((ret = jffs2_do_mount_fs(c))) 534 if ((ret = jffs2_do_mount_fs(c)))
523 goto out_inohash; 535 goto out_inohash;
524 536
525 ret = -EINVAL;
526
527 D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n")); 537 D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n"));
528 root_i = iget(sb, 1); 538 root_i = jffs2_iget(sb, 1);
529 if (is_bad_inode(root_i)) { 539 if (IS_ERR(root_i)) {
530 D1(printk(KERN_WARNING "get root inode failed\n")); 540 D1(printk(KERN_WARNING "get root inode failed\n"));
531 goto out_root_i; 541 ret = PTR_ERR(root_i);
542 goto out_root;
532 } 543 }
533 544
545 ret = -ENOMEM;
546
534 D1(printk(KERN_DEBUG "jffs2_do_fill_super(): d_alloc_root()\n")); 547 D1(printk(KERN_DEBUG "jffs2_do_fill_super(): d_alloc_root()\n"));
535 sb->s_root = d_alloc_root(root_i); 548 sb->s_root = d_alloc_root(root_i);
536 if (!sb->s_root) 549 if (!sb->s_root)
@@ -546,6 +559,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
546 559
547 out_root_i: 560 out_root_i:
548 iput(root_i); 561 iput(root_i);
562out_root:
549 jffs2_free_ino_caches(c); 563 jffs2_free_ino_caches(c);
550 jffs2_free_raw_node_refs(c); 564 jffs2_free_raw_node_refs(c);
551 if (jffs2_blocks_use_vmalloc(c)) 565 if (jffs2_blocks_use_vmalloc(c))
@@ -615,9 +629,9 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
615 jffs2_do_unlink() would need the alloc_sem and we have it. 629 jffs2_do_unlink() would need the alloc_sem and we have it.
616 Just iget() it, and if read_inode() is necessary that's OK. 630 Just iget() it, and if read_inode() is necessary that's OK.
617 */ 631 */
618 inode = iget(OFNI_BS_2SFFJ(c), inum); 632 inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
619 if (!inode) 633 if (IS_ERR(inode))
620 return ERR_PTR(-ENOMEM); 634 return ERR_CAST(inode);
621 } 635 }
622 if (is_bad_inode(inode)) { 636 if (is_bad_inode(inode)) {
623 printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d\n", 637 printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d\n",