diff options
Diffstat (limited to 'fs/jffs2/fs.c')
-rw-r--r-- | fs/jffs2/fs.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index d2e06f7ea96f..e26ea78c7892 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -97,11 +97,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
97 | ri->gid = cpu_to_je16((ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid); | 97 | ri->gid = cpu_to_je16((ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid); |
98 | 98 | ||
99 | if (ivalid & ATTR_MODE) | 99 | if (ivalid & ATTR_MODE) |
100 | if (iattr->ia_mode & S_ISGID && | 100 | ri->mode = cpu_to_jemode(iattr->ia_mode); |
101 | !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID)) | ||
102 | ri->mode = cpu_to_jemode(iattr->ia_mode & ~S_ISGID); | ||
103 | else | ||
104 | ri->mode = cpu_to_jemode(iattr->ia_mode); | ||
105 | else | 101 | else |
106 | ri->mode = cpu_to_jemode(inode->i_mode); | 102 | ri->mode = cpu_to_jemode(inode->i_mode); |
107 | 103 | ||
@@ -230,16 +226,23 @@ void jffs2_clear_inode (struct inode *inode) | |||
230 | jffs2_do_clear_inode(c, f); | 226 | jffs2_do_clear_inode(c, f); |
231 | } | 227 | } |
232 | 228 | ||
233 | void jffs2_read_inode (struct inode *inode) | 229 | struct inode *jffs2_iget(struct super_block *sb, unsigned long ino) |
234 | { | 230 | { |
235 | struct jffs2_inode_info *f; | 231 | struct jffs2_inode_info *f; |
236 | struct jffs2_sb_info *c; | 232 | struct jffs2_sb_info *c; |
237 | struct jffs2_raw_inode latest_node; | 233 | struct jffs2_raw_inode latest_node; |
238 | union jffs2_device_node jdev; | 234 | union jffs2_device_node jdev; |
235 | struct inode *inode; | ||
239 | dev_t rdev = 0; | 236 | dev_t rdev = 0; |
240 | int ret; | 237 | int ret; |
241 | 238 | ||
242 | D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); | 239 | D1(printk(KERN_DEBUG "jffs2_iget(): ino == %lu\n", ino)); |
240 | |||
241 | inode = iget_locked(sb, ino); | ||
242 | if (!inode) | ||
243 | return ERR_PTR(-ENOMEM); | ||
244 | if (!(inode->i_state & I_NEW)) | ||
245 | return inode; | ||
243 | 246 | ||
244 | f = JFFS2_INODE_INFO(inode); | 247 | f = JFFS2_INODE_INFO(inode); |
245 | c = JFFS2_SB_INFO(inode->i_sb); | 248 | c = JFFS2_SB_INFO(inode->i_sb); |
@@ -250,9 +253,9 @@ void jffs2_read_inode (struct inode *inode) | |||
250 | ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); | 253 | ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); |
251 | 254 | ||
252 | if (ret) { | 255 | if (ret) { |
253 | make_bad_inode(inode); | ||
254 | up(&f->sem); | 256 | up(&f->sem); |
255 | return; | 257 | iget_failed(inode); |
258 | return ERR_PTR(ret); | ||
256 | } | 259 | } |
257 | inode->i_mode = jemode_to_cpu(latest_node.mode); | 260 | inode->i_mode = jemode_to_cpu(latest_node.mode); |
258 | inode->i_uid = je16_to_cpu(latest_node.uid); | 261 | inode->i_uid = je16_to_cpu(latest_node.uid); |
@@ -303,19 +306,14 @@ void jffs2_read_inode (struct inode *inode) | |||
303 | if (f->metadata->size != sizeof(jdev.old) && | 306 | if (f->metadata->size != sizeof(jdev.old) && |
304 | f->metadata->size != sizeof(jdev.new)) { | 307 | f->metadata->size != sizeof(jdev.new)) { |
305 | printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size); | 308 | printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size); |
306 | up(&f->sem); | 309 | goto error_io; |
307 | jffs2_do_clear_inode(c, f); | ||
308 | make_bad_inode(inode); | ||
309 | return; | ||
310 | } | 310 | } |
311 | D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); | 311 | 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) { | 312 | ret = jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size); |
313 | if (ret < 0) { | ||
313 | /* Eep */ | 314 | /* Eep */ |
314 | printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); | 315 | printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); |
315 | up(&f->sem); | 316 | goto error; |
316 | jffs2_do_clear_inode(c, f); | ||
317 | make_bad_inode(inode); | ||
318 | return; | ||
319 | } | 317 | } |
320 | if (f->metadata->size == sizeof(jdev.old)) | 318 | if (f->metadata->size == sizeof(jdev.old)) |
321 | rdev = old_decode_dev(je16_to_cpu(jdev.old)); | 319 | rdev = old_decode_dev(je16_to_cpu(jdev.old)); |
@@ -335,6 +333,16 @@ void jffs2_read_inode (struct inode *inode) | |||
335 | up(&f->sem); | 333 | up(&f->sem); |
336 | 334 | ||
337 | D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); | 335 | D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); |
336 | unlock_new_inode(inode); | ||
337 | return inode; | ||
338 | |||
339 | error_io: | ||
340 | ret = -EIO; | ||
341 | error: | ||
342 | up(&f->sem); | ||
343 | jffs2_do_clear_inode(c, f); | ||
344 | iget_failed(inode); | ||
345 | return ERR_PTR(ret); | ||
338 | } | 346 | } |
339 | 347 | ||
340 | void jffs2_dirty_inode(struct inode *inode) | 348 | void jffs2_dirty_inode(struct inode *inode) |
@@ -522,15 +530,16 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) | |||
522 | if ((ret = jffs2_do_mount_fs(c))) | 530 | if ((ret = jffs2_do_mount_fs(c))) |
523 | goto out_inohash; | 531 | goto out_inohash; |
524 | 532 | ||
525 | ret = -EINVAL; | ||
526 | |||
527 | D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n")); | 533 | D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n")); |
528 | root_i = iget(sb, 1); | 534 | root_i = jffs2_iget(sb, 1); |
529 | if (is_bad_inode(root_i)) { | 535 | if (IS_ERR(root_i)) { |
530 | D1(printk(KERN_WARNING "get root inode failed\n")); | 536 | D1(printk(KERN_WARNING "get root inode failed\n")); |
531 | goto out_root_i; | 537 | ret = PTR_ERR(root_i); |
538 | goto out_root; | ||
532 | } | 539 | } |
533 | 540 | ||
541 | ret = -ENOMEM; | ||
542 | |||
534 | D1(printk(KERN_DEBUG "jffs2_do_fill_super(): d_alloc_root()\n")); | 543 | D1(printk(KERN_DEBUG "jffs2_do_fill_super(): d_alloc_root()\n")); |
535 | sb->s_root = d_alloc_root(root_i); | 544 | sb->s_root = d_alloc_root(root_i); |
536 | if (!sb->s_root) | 545 | if (!sb->s_root) |
@@ -546,6 +555,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) | |||
546 | 555 | ||
547 | out_root_i: | 556 | out_root_i: |
548 | iput(root_i); | 557 | iput(root_i); |
558 | out_root: | ||
549 | jffs2_free_ino_caches(c); | 559 | jffs2_free_ino_caches(c); |
550 | jffs2_free_raw_node_refs(c); | 560 | jffs2_free_raw_node_refs(c); |
551 | if (jffs2_blocks_use_vmalloc(c)) | 561 | if (jffs2_blocks_use_vmalloc(c)) |
@@ -615,9 +625,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. | 625 | 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. | 626 | Just iget() it, and if read_inode() is necessary that's OK. |
617 | */ | 627 | */ |
618 | inode = iget(OFNI_BS_2SFFJ(c), inum); | 628 | inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum); |
619 | if (!inode) | 629 | if (IS_ERR(inode)) |
620 | return ERR_PTR(-ENOMEM); | 630 | return ERR_CAST(inode); |
621 | } | 631 | } |
622 | if (is_bad_inode(inode)) { | 632 | if (is_bad_inode(inode)) { |
623 | printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d\n", | 633 | printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d\n", |