diff options
Diffstat (limited to 'fs/jffs2/fs.c')
-rw-r--r-- | fs/jffs2/fs.c | 56 |
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 | ||
233 | void jffs2_read_inode (struct inode *inode) | 233 | struct 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 | |||
343 | error_io: | ||
344 | ret = -EIO; | ||
345 | error: | ||
346 | up(&f->sem); | ||
347 | jffs2_do_clear_inode(c, f); | ||
348 | iget_failed(inode); | ||
349 | return ERR_PTR(ret); | ||
338 | } | 350 | } |
339 | 351 | ||
340 | void jffs2_dirty_inode(struct inode *inode) | 352 | void 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); |
562 | out_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", |